1. 事件流
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
1.1 事件冒泡
如果你单击了页面中的<div>元素,那么这个 click 事件会按照如下顺序传播:
<div> -> <body> -> <html> -> <document>
1.2 事件捕获
与事件冒泡完全相反
1.3 DOM 事件流
事件捕获阶段 -> 处于目标阶段 -> 事件冒泡阶段
2. 事件处理程序
2.1 HTML 事件处理程序
<input type="button" value="Click Me" onclick="alert(this.value)">
2.2 DOM0 级事件处理程序
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
};
2.3 DOM2 级事件处理程序
//addEventListener();
//removeEventListener();
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click", handler, false);
//这里省略了其他代码
btn.removeEventListener("click", handler, false); //有效!
- 大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。
最好只在需要在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。如果不是特别需要,
我们不建议在事件捕获阶段注册事件处理程序。
2.4 IE 事件处理程序
//attachEvent();
//detachEvent();
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert(this === window); //true
});
- 在使用 attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,跟 DOM0 级事件不同,因此 this 等于 window。
- 与 DOM 方法不同的是,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
2.5 跨浏览器的事件处理程序
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;
}
}
};
- 要保证处理事件的代码能在大多数浏览器下一致地运行,只需关注冒泡阶段。
3. 事件对象
3.1 DOM 中的事件对象
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.type); //"click"
};
btn.addEventListener("click", function(event){
alert(event.type); //"click"
}, false);
<input type="button" value="Click Me" onclick="alert(event.type)"/>
//在需要通过一个函数处理多个事件时,可以使用 type 属性。例如:
var btn = document.getElementById("myBtn");
var handler = function(event){
switch(event.type){
case "click":
alert("Clicked");
break;
case "mouseover":
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = "";
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
//阻止事件的默认值
var link = document.getElementById("myLink");
link.onclick = function(event){
event.preventDefault();
};
//stopPropagation(),取消进一步的事件捕获或冒泡
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert("Clicked");
event.stopPropagation();
};
document.body.onclick = function(event){
alert("Body clicked");
};
//eventPhase,确定事件正位于事件流的哪个阶段
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.eventPhase); //2
};
document.body.addEventListener("click", function(event){
alert(event.eventPhase); //1
}, true);
document.body.onclick = function(event){
alert(event.eventPhase); //3
};
3.2 IE 中的事件对象
3.3 跨浏览器的事件对象
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;
}
},
getEvent: function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false;
}
},
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;
}
},
stopPropagation: function(event){
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
4. 事件类型
4.1 UI 事件
- load 事件;
- unload 事件;
- resize 事件;
- scroll 事件;
4.2 焦点事件
- focusout;
- focusin;
- blur;
- DOMFocusOut;
- focusin;
- DOMFocusIn;
4.3 鼠标与滚轮事件
- clientX,clientY;
- pageX,pageY;scrollLeft,scrollTop;
- screenX,screenY;
- shiftKey,ctrlKey,altKey,metaKey;
4.4 键盘与文本事件
4.5 复合事件
4.6 变动事件
4.7 HTML5 事件
- contextmenu 事件;
- beforeunload 事件;
- DOMContentLoaded 事件;
- readystatechange 事件;
- pageshow 和 pagehide 事件;
- hashchange 事件;
4.8 设备事件
- orientationchange 事件;
- MozOrientation 事件;
- deviceorientation 事件;
- devicemotion 事件;
4.9 触摸与手势事件
5. 内存和性能
5.1 事件委托
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id){
case "doSomething":
document.title = "I changed the document's title";
break;
case "goSomewhere":
location.href = "http://www.wrox.com";
break;
case "sayHi":
alert("hi");
break;
}
});
5.2 移除事件处理程序
6. 模拟事件
6.1 DOM 中的事件模拟
var btn = document.getElementById("myBtn");
//创建事件对象
var event = document.createEvent("MouseEvents");
//初始化事件对象
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
//触发事件####6.2 IE 中的事件模拟
btn.dispatchEvent(event);
6.2 IE 中的事件模拟
var textbox = document.getElementById("myTextbox");
//创建事件对象
var event = document.createEventObject();
//初始化事件对象
event.altKey = false;
event.ctrlKey = false;
event.shiftKey = false;
event.keyCode = 65;
//触发事件
textbox.fireEvent("onkeypress", event);