事件流
事件流描述的是从页面中接收事件的顺序
事件流 | 描述 |
---|---|
事件冒泡 | IE的事件流,事件从最具体的节点开始,然后逐级向上冒泡到不具体的节点 |
事件捕获 | 不具体的节点先接收到事件,具体的节点最后接收到事件 |
DOM事件流 | DOM事件流包含三个阶段:事件捕获、处于目标事件阶段、事件冒泡阶段 |
事件处理程序
事件处理程序包括:HTML事件处理程序、DOM0级事件处理程序、DOM2级事件处理程序和IE事件处理程序
HTML事件处理程序
在HTML代码中直接指定绑定的事件处理程序(可以是函数也可以是js代码)。例如:
<input onclick="showOn()">显示</input>
<input onclick="console.log('hello')">显示</input>
DOM0级事件处理程序
在目标元素上添加事件处理程序属性。
var ele = document.getElementById("test");
ele.onClick = function(){
console.log("hello");
}
如果要删除DOM0级事件处理程序,将事件处理程序属性值设置为null
即可。
ele.onClick = null;
DOM2级事件处理程序
DOM2级事件处理程序提供了两个方法,用于指定添加和删除事件处理程序的操作:addEventListener()
和removeEventListener()
。方法接收三个参数:事件名、事件处理程序、一个布尔值。布尔值为true
表示在事件捕获阶段调用事件处理程序,为false
表示在事件冒泡阶段调用事件处理程序。
var ele = document.getElementById("test");
function show(){
console.log("hello");
}
ele.addEventListener("click", show, false); //冒泡阶段调用
ele.removeEventListener("click", show, false); //传入相同参数
注意: 通过addEventListener()
添加的事件处理程序,只能通过removeEventListener()
来移除。移除时传入相同的参数,并且通过addEventListener()
添加的匿名函数无法移除。
支持: IE9、Firefox、Safar、Chrome、Opera
IE事件处理程序
IE中通过attachEvent()
和detachEvent()
来添加和删除事件处理程序。两个方法接收两个参数:事件处理程序名称、事件处理程序函数。IE8及更早版本支持事件冒泡,通过attachEvent()
添加的事件处理程序都会被添加到冒泡阶段。
var ele = document.getElementById("test");
function show(){
console.log("hello");
}
ele.attachEvent("onclick", show);
ele.detachEvent("onclick", show);
跨浏览器的事件处理程序
var EventUtli = {
addHandler : function(element, event, handler){
if( element.addEventListener ){
element.addEventListener(event, handler, false);
}else if( event.attachEvent ){
element.attachEvent("on"+event, handler);
}else{
element["on"+event] = handler;
}
},
removeHandler : function(element, event, handler){
if( element.addEventListener ){
element.removeEventListener(event, handler, false);
}else if( event.attachEvent ){
element.detachEvent("on"+event, handler);
}else{
element["on"+event] = null;
}
}
};
事件对象
事件触发时,会产生一个事件对象,该对象中含有与事件有关的相关信息
DOM中事件对象
事件对象将作为一个参数传入DOM0级和DOM2级事件处理程序中,对于HTML事件处理程序,事件对象是代码中的event变量。
var ele = document.getElementById("test");
// DOM0
ele.onClick = function(event){}
// DOM2
ele.addEventListener("click", function(event){}, false);
// HTML
<input onclick="console.log('event.type')">显示</input>
IE中事件对象
访问IE中事件对象有几种方式,根据定义事件处理程序的方法有所不同。用DOM0级方法定义事件处理程序时,事件对象作为window对象的属性存在。用attachEvent()
方法添加事件处理程序时,事件对象作为参数传入事件处理程序。
var ele = document.getElementById("test");
// DOM0
ele.onclick = function(){
var event = window.event;
console.log(event.type);
}
// attachEvent()
ele.attachEvent("onclick", function(event){
console.log(event.type);
});
事件对象的属性和方法
DOM中:
属性/方法 | 类型 | 读写 | 说明 |
---|---|---|---|
type | String | 只读 | 被触发的事件类型 |
bubbles | Boolean | 只读 | 事件是否冒泡 |
cancelable | Boolean | 只读 | 是否可以取消事件默认行为 |
target | Element | 只读 | 事件的实际目标(触发事件的元素) |
currentTarget | Element | 只读 | 事件处理程序当前正在处理事件的那个元素(事件绑定的元素) |
eventPhase | Integet | 只读 | 事件处理程序的阶段:1为捕获、2为处于目标、3表示冒泡 |
preventDefault() | Function | 只读 | 取消事件的默认行为(前提是cancelable为true) |
stopImmediatePropagation() | Function | 只读 | 取消事件的进一步捕获或者冒泡 |
stopPropagation() | Function | 只读 | 取消事件的进一步捕获或者冒泡 |
IE中:
属性/方法 | 类型 | 读写 | 说明 |
---|---|---|---|
cancelBubble | Boolean | 读写 | 默认为false,设置为true就可以取消事件冒泡 |
returnValue | Boolean | 读写 | 默认为true,设置为false就可以取消事件的默认行为 |
type | String | 只读 | 被触发的事件类型 |
srcElement | Element | 只读 | 事件的目标 |
跨浏览器的事件对象
var EventUtli = {
addHandler : function(element, type, handler){},
removeHandler : function(element, 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;
}
},
stopPropagation : function(event){
if(evevt.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
};
性能和内存
事件委托
利用事件冒泡,将多个元素的同类事件绑定到更高一级的元素上,减少事件处理程序的数量。在事件处理程序中,传入事件对象event,通过event的target
属性来判断事件当前冒泡到的元素。
e.g.
<!-- HTML代码 -->
<!--为li元素绑定点击事件,在控制台上显示li元素的内容-->
<ul id="all">
<li id="a">A</li>
<li id="b">B</li>
<li id="c">C</li>
</ul>
未使用事件委托:
// js代码
var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
function show(){
console.log(this.innerText);
}
a.onclick = show;
b.onclick = show;
c.onclick = show;
使用事件委托
var all = document.getElementById("all");
function show(){
console.log(this.innerText);
}
all.onclick = function(event){
// event.target指向事件冒泡到的元素
if(event.target.tagName.toLowerCase() === "li"){
show.call(event.target);
}
}
移除事件处理程序
移除页面上带事件处理程序的元素时,事件处理程序可能无法被当成垃圾回收。在移除元素前,先移除该元素上的事件处理程序。