导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

术语

事件句柄

所谓的事件句柄就是一个将元素的特定事件与某个函数关联起来,比如 onclickonmouseover 等都是事件句柄,它们会指向一个给定的函数,也就是事件发生时要执行的操作。例如:

div.onclick = function() {
	// todo...
}

// 👆🏻 整体叫做 事件句柄,其中 onclick 单独拆出来叫 句柄
// 通常说的 事件句柄的绑定形式 就是上面这种形式

事件源

事件作用在谁身上,谁就是事件源。

比如网页元素中 a 标签有 onclick 事件,当点击 a 发生 onclick 事件时,事件源就是 a 标签。

绑定事件处理函数

1. HTML 中直接绑定 - 内联 / 行内事件监听器

<div onclick="test()" onmouseover="test2()"></div>

2. JS 中获取 DOM 元素后绑定

div.onclick = function() {};

同时绑定多个处理函数,后边的会覆盖前面的

div.onclick = function() { console.log(1); };
div.onclick = function() { console.log(2); };

// 只会打印 2
<div onclick="console.log(1)">点击我</div>
<script>
  div.onclick = function() { console.log(2); };
  
  // 只会打印 2
</script>

3. addEventListener(事件类型, 事件处理函数, useCapture) 事件监听器

oBtn.addEventListener('click', function() {
    this.innerHTML = '加载中..';
}, false);
oBtn.addEventListener('click', function() {
    console.log('加载更多事件');
}, false);
// 2个绑定都会执行
oBtn.addEventListener('click', test, false);
oBtn.addEventListener('click', test, false);
function test() {
    console.log(1);
}
// 只会执行一次打印,因为绑定的是同一个函数引用

4. attachEvent (事件类型,事件处理函数)

oBtn.attachEvent('onclick', function() {
    test.call(oBtn);
})
function test() {} // 解决 attachEvent 中 this 指向问题
oBtn.attachEvent('onclick', test, false);
oBtn.attachEvent('onclick', test, false);
function test() {
    console.log(1);
}
// 执行两次打印

⭐️ this 指向与事件绑定

html 中直接绑定

<div class="container" onclick="handleClick()">Click Me</div>
<!-- onclick 必须加 () -->

<script>
function handleClick(e) {
  console.log(this, e); // window, undefined
}
</script>

<div class="container" onclick="console.log(this)">Click Me</div>

<script>
// 这个时候 this 是 div.container
</script>

<div class="container" onclick="handleClick.call(this, event)">Click Me</div>

<script>
function handleClick(e) {
  console.log(this, e); // div.container, event
}
</script>

js 通过 on 绑定

<div class="container"></div>
<script>
const container = document.getElementsByClassName('container')[0];
container.onclick = function(e) {
  console.log(this, e); // div.container, event
}
</script>

addEventListener

<div class="container"></div>
<script>
const container = document.getElementsByClassName('container')[0];
container.addEventListener('click', function(e) {
  console.log(this, e); // div.container, evet
});
</script>

⭐️ 封装事件处理函数

function addEvent(el, type, fn) {
	if (el.addEventListener) {
  	el.addEventListener(type, fn, false);
  } else if (el.attachEvent) {
  	el.attachEvent('on' + type, function() {
    	fn.call(el);
    });
  } else {
  	el['on' + type] = fn;
  }
}

解除事件绑定

oBtn.addEventListener('click', test, false);
oBtn.addEventListener('click', test, false);

// 函数提出来
function test() {
	this.className = '';
  this.innerHTML = '';
  this.removeEventListener('click', test, false);
}
// 给匿名函数起名字
oBtn.addEventListener('click', function test() {
	this.className = '';
  this.innerHTML = '';
  this.removeEventListener('click', test, false);
})
// 非严格模式下
oBtn.addEventListener('click', function() {
	this.className = '';
  this.innerHTML = '';
  this.removeEventListener('click', arguments.callee, false);
})