js和html的交互通过事件。事件流描述页面接受事件的顺序。事件流分为事件冒泡和事件捕获。
DOM2 Events规范规定事件流分为3个阶段:事件捕获、到达事件和事件冒泡。
-
事件处理程序
html事件处理程序
问题:1、时机问题,有可能html元素已经显示在页面上,用户都与其进行交互,而事件处理程序的代码还无法执行。
2、对事件处理程序作用域链的扩展在不同浏览器中可能导致不同的结果
3、html与js强耦合,如果修改事件处理程序,必须在html和js中子u该代码
DOM0事件处理程序
把一个函数赋值给DOM元素的一个事件处理程序属性
let btn = document.getElementById("myBtn");
btn.onclick = function() {
console.log(this.id); // "myBtn"
};
btn.onclick = null; // 移除事件处理程序
DOM2事件处理程序
赋值:addEventListener()
移除:removeEventListener()
let btn = document.getElementById("myBtn");
btn.addEventListener("click", () => {
console.log(this.id);
}, false);
// 其他代码
btn.removeEventListener("click", function() { // 没有效果!
console.log(this.id);
}, false);
let btn = document.getElementById("myBtn");
let handler = function() {
console.log(this.id);
};
btn.addEventListener("click", handler, false);
// 其他代码
btn.removeEventListener("click", handler, false); // 有效果!
通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 并传入与添加时同样的参数来移除。
DOM2优势:可以为同一个事件添加多个事件处理程序
IE事件处理程序
赋值:attachEvent()
移除:detachEvent()
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
console.log(this === window); // true
});
IE中使用attachEvent()与使用DOM0方式的主要区别是事件处理程序的作用域。使用DOM0时,事件处理程序中的this值等于目标元素。而使用attachEvent()时,事件处理程序是在全局作用域中运行的,因此,this等于window.
与DOM2事件处理程序一样可以为同一个事件添加多个事件处理程序,但事件处理程序会以添加他们的顺序反序输出。
跨浏览器事件处理程序
以跨浏览器兼容的方式处理事件。创建一个addHandler()方法。这个方法的任务根据需要分别使用DOM0方式、DOM2方式或IE方式来添加事件处理程序。在EventUtil对象添加一个方法,以实现浏览器事件处理。
var EventUtil = {
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;
}
}
};
参考文献:
《JavaScript高级程序设计(第四版)》