本文介绍原生JavaScript中事件添加与删除的兼容封装方法,涵盖IE与非IE浏览器的处理差异。重点解析addEventListener的第三个参数useCapture,阐明其控制事件捕获与冒泡顺序的原理,并通过嵌套元素示例说明不同参数设置对事件执行流程的影响。
原生JS事件绑定与移除的兼容封装
在IE浏览器中,添加和删除事件分别使用attachEvent与detachEvent方法;而在其他符合标准的现代浏览器中,则采用addEventListener和removeEventListener。为了简化跨浏览器的开发工作,下面对事件的添加与删除操作进行了统一封装,具体实现代码如下。
/**
* @description 事件绑定,兼容各浏览器
* @param target
* 事件触发对象
* @param type
* 事件
* @param func
* 事件处理函数
*/
function bind(target, type, func) {
if (target.addEventListener) {// 非ie 和ie9
target.addEventListener(type, func, false);
} else if (target.attachEvent) { // ie6到ie8
target.attachEvent("on" + type, func);
} else {
target["on" + type] = func; // ie5
}
}
/**
* @description 事件移除,兼容各浏览器
* @param target
* 事件触发对象
* @param type
* 事件
* @param func
* 事件处理函数
*/
function unbind(target, type, func) {
if (target.removeEventListener) {
target.removeEventListener(type, func, false);
} else if (target.detachEvent) {
target.detachEvent("on" + type, func);
} else {
target["on" + type] = null;
}
}
addEventListener第三个参数:useCapture机制解析
关于addEventListener方法的第三个参数,这里补充一些关键说明。
深入理解addEventListener的第三个参数
W3C DOM规范中用于注册事件触发的函数名为AddEventListener。过去我并未深入探究该函数第三个参数的具体作用,往往随意设置且未察觉差异。直到近期阅读ppk on javascript文章后才明确其含义,尽管DOM标准文档中早已有此参数的详细说明,但我此前并未查阅。
该参数名为useCapture,类型为布尔值(true或false)。若设为true,浏览器将采用捕获(Capture)模式;若设为false,则采用冒泡(Bubbling)模式。此参数仅在特定场景下产生实际影响,通常建议设置为false。其影响主要出现在目标元素(target element)存在祖先元素(ancestor element),且祖先元素也绑定了相同事件处理函数的情况下,具体区别可通过图示理解。

示例包含两层嵌套的div元素。
如图所示,示例中包含两层div元素,且均绑定了click事件。通常情况下,若在内层蓝色元素上点击,不仅会触发蓝色元素的click事件,还会同时触发外层红色元素的click事件。useCapture参数即用于控制这两个click事件的执行顺序。当参数为false时,采用冒泡机制,流程由内向外,因此先执行蓝色元素的click事件,再执行红色元素的click事件;当参数为true时,采用捕获机制,与冒泡相反,流程由外向内,因此先执行红色元素的click事件,再执行蓝色元素的click事件。附有两个示例文件,分别对应capture和bubbling模式,两者仅在此参数上存在差异,运行结果可见事件发生顺序不同。
若不同层级的元素使用了不同的useCapture设置,事件执行流程将变得复杂:系统会先从最外层元素向目标元素查找并执行被设定为capture的事件;到达目标元素并执行其事件后,再沿原路向外查找并执行被设定为bubbling的事件。