Open jtwang7 opened 3 years ago
目的:兼容 DOM0 / DOM2 / IE 方式添加事件处理程序
const EvnetUtil = {
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, handler);
} else {
element['on' + type] = handler;
}
},
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
}
}
首先检测传入元素是否存在 DOM2 方式,若存在则使用该方式;否则检查是否存在 IE 方式,若存在则使用该方式。若前两种方式浏览器都不支持,则使用 DOM0 方式 (现代浏览器中不会执行到这一步)。
注意: IE 和 DOM0 级事件处理程序需要传入的是事件处理程序的名称,而不是事件类型,即必须在事件类型前加上 "on"。
上述兼容方法并没有解决所有跨浏览器一致性的问题,例如 IE 的作用域问题、多个事件处理程序执行顺序问题,DOM0 级不支持为一个事件添加多个处理程序等。
HTML 事件处理程序
HTML 事件处理程序支持在 HTML 标签的特定元素中,使用事件处理程序的名字以 HTML 属性的形式来指定响应事件的调用函数。
在 HTML 属性中定义的事件处理程序可以包含精确的动作指令(如上),也可以调用页面其他地方定义的脚本:
HTML 事件处理程序的缺点
时机问题:事件处理程序定义在 HTML 标签属性上,很可能在 HTML 标签元素已经完成渲染时,事件处理程序的回调函数还未完成定义,导致用户与元素交互时,无法找到对应的回调函数执行代码而报错。
不同浏览器对事件处理程序作用域链的扩展的处理结果可能不同。不同 JavaScript 引擎中标识符解析的规则存在差异,因此访问无限定的对象成员可能导致错误。
HTML 与 JavaScript 强耦合:JavaScript 代码脚本与 HTML 标签属性强绑定,如果修改事件处理程序,必须在 HTML 和 JavaScript 两个地方修改代码。这也是开发者不使用 HTML 事件处理程序,转而使用 JavaScript 指定事件处理程序的主要原因。
DOM0 事件处理程序
DOM0 事件处理程序支持在 JavaScript 中指定事件处理程序:把一个函数赋值给 DOM 元素的一个事件处理程序属性。
DOM2 事件处理程序
DOM2 Events 规范为事件处理程序的赋值和移除定义了两个方法:
addEventListener(type, handler, useCapture)
removeEventLIstener(type, handler, useCapture)
这两个方法暴露在 所有 DOM 节点上,并接收 3 个参数:
同 DOM0 方式类似,DOM2 方式绑定的事件处理程序同样在目标元素的作用域中执行,即 this 指向目标元素。
通过
addEventListener()
添加的事件处理程序只能使用removeEventListener()
并传入与添加时同样的参数来移除,这意味着 addEventListener 添加的匿名函数是无法移除的。DOM0 与 DOM2 的差异
IE 事件处理程序
IE 为事件处理程序的赋值和移除定义了两个方法:
attachEvent(name, handler)
detackEvent(name, handler)
方法接受两个参数:
IE 与 DOM0 / DOM2 异同
事件处理程序的作用域
IE 添加的事件处理程序作用域是在全局作用域中运行,this 指向 window 对象。 DOM 级方式添加的事件处理程序作用域是目标元素的作用,this 指向目标元素对象。
事件流
IE 和 DOM0 方式添加的事件处理程序都被添加到事件的冒泡阶段进行。 DOM2 可自定义事件流处理方式,默认在冒泡阶段执行事件处理程序。
重复事件处理程序处理方式
DOM0 不支持重复事件的连续触发,重复事件会覆盖上一次的事件定义,从而只会响应最后一次定义的事件处理程序。 DOM2 可以为同一事件添加多个事件处理程序,并按照添加顺序触发事件处理程序。 IE 可以为同一事件添加多个事件处理程序,但按照添加的顺序反向触发。