监听函数
浏览器的事件模型,通过监听函数(listener)对事件做出反应。事件发生后,浏览器监听到了这个事件,就会执行对应的监听函数。
监听方法
window.addEventListener('load', doSomething, false);
EventTarget.addEventListener()用于在当前节点或对象上,定义一个特定事件的监听函数。一旦这个事件发生,就会执行监听函数。该方法没有返回值。
该方法接受三个参数:
- type:事件名称,大小写敏感。
- listener:监听函数。事件发生时,会调用该监听函数。
- useCapture:布尔值,表示监听函数是否在捕获阶段(capture)触发(参见后文《事件的传播》部分),默认为false(监听函数只在冒泡阶段被触发)。该参数可选。
例子👇
function hello() {
console.log('Hello world');
}
var button = document.getElementById('btn');
button.addEventListener('click', hello, false);
事件的传播
一个事件发生后,会在子元素和父元素之间传播(propagation),这种传播会分成三个阶段:
- 第一阶段:从window对象传导到目标节点(上层传到底层),称为“捕获阶段”(capture phase)。
- 第二阶段:在目标节点上触发,称为“目标阶段”(target phase)。
- 第三阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。
这种三阶段的传播模型,使得同一个事件会在多个节点上触发。也就是当一个事件发生后,会先进行事件捕获,再进行事件冒泡,这两个部分都会执行,程序员选择把事件加在捕获阶段还是冒泡阶段
事件传播的模型👇
捕获不可以取消,冒泡可以取消
e.stopPropagetion() 可以中断冒泡。
有的事件不支持取消冒泡,比如scroll event,具体是否可以取消可以查引文版MDN
事件代理
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。
意义:
- 省内存。当需要监听多个元素的事件时,只需要给希望监听的父元素上加一个事件即可。
- 可以监听动态元素。浏览器只看点击的时候是否有这个元素,不管这个元素是多早出现的。
例子👇
var ul = document.querySelector('ul');
ul.addEventListener('click', function (event) {
if (event.target.tagName.toLowerCase() === 'li') {
// some code
}
});
上面代码中,click事件的监听函数定义在ul节点,但是实际上,它处理的是子节点li的click事件。这样做的好处是,只要定义一个监听函数,就能处理多个子节点的事件,而不用在每个li节点上定义监听函数。而且以后再添加子节点,监听函数依然有效。