说到事件就要先科普事件流。
浏览器中的事件流分为两种,事件捕获流和事件冒泡流:
一般浏览器都是默认使用事件冒泡。并且冒泡直到window才停。
DOM2级事件流有如上图的三个阶段,捕获,处于目标阶段,冒泡。要注意,关于事件冒泡或者捕获,是指在触发一个事件的时候,在事件流中会触发相关元素的指定事件。比如指定了click事件,那么在事件流中就会触发相关元素的click事件,如果相关元素没有指定click事件,那么自然就不会有『触发』相关元素的指定事件这一说。
在非IE浏览器中:
事件处理器用addEventListener("click",function(){})绑定,用removeEventListener("click',fun_name)解绑。如果绑定函数的时候执行事件是个匿名函数,就不能解绑,因为没有对应的函数名。
对于addEventListener(事件名,执行函数,是否捕获)。第三个参数默认是false,表示在冒泡阶段发生。如果被设置成true,则在事件的捕获阶段发生。
例如:
<span style="font-size:18px;"><span style="font-size:18px;color:#333333;">btn.addEventListener("click",function(ev){
<span style="white-space:pre"> </span>console.log(this.id,ev.eventPhase);
});
<span style="white-space:pre"> </span>
box.addEventListener("click",function(ev){
<span style="white-space:pre"> </span>console.log(this.id,ev.eventPhase);
});</span></span>
html的文档结构是body > container > box > btn:
<span style="font-size:18px;"><span style="font-size:18px;color:#333333;"><div class="container" id="container" style="width: 500px; height: 500px; background: red">
<div class="box" id="box" style="width: 300px; height: 300px; background-color: yellow;">
<button id="btn" type="button">Click</button>
</div>
</div></span></span>
这时候点击btn,控制台显示btn-2, box-3说明先触发btn的click事件,然后在冒泡阶段触发了box的click事件。如果把box的绑定函数的第三个参数变成true:
<span style="font-size:18px;"><span style="font-size:18px;color:#333333;">box.addEventListener("click",function(ev){
console.log(this.id,ev.eventPhase);
},true);</span></span>
这时候点击btn,控制台就显示box-1,btn-2。说明在捕获阶段,触发了box的click事件。
如果元素是被点击的对象,那么设不设置true都没什么影响。第三个参数的设置是为了规定元素在流中事件被触发的先后。
对于每个事件执行的函数,都会默认传入一个event对象,表示事件对象。
event对象有几个主要的属性:
target => 当前事件的真正对象
currentTarget => 执行这个函数的对象(当前函数的this指针指向的对象)
eventPhase => 事件处于程序处理的阶段
比如对于上面的例子,点击btn,执行box的click函数的时候,event.target还是指向btn,而event.currentTarget指向的是box
event对象的常用主要方法:
stopPropagation => 阻止事件继续执行。可以停止冒泡,也可以停止捕获
preventDefault => 取消事件的默认行为
如果将box的执行器改为:
<span style="font-size:18px;"><span style="font-size:18px;color:#333333;">box.addEventListener("click",function(ev){
console.log(this.id,ev.eventPhase);
ev.stopPropagation();
},true);</span></span>
那么事件就终止在box的捕获阶段,也不会捕获到btn对象。所以这时候点击btn,只会执行box的click函数。
在IE中:
用attachEvent("onclick",funciton(),bubble)来绑定事件,用detachEvent("onclick",fun_name)对事件解绑。
对比其他浏览器,事件名要加上"on"前缀。
event对象与其他浏览器中略有不同,主要的属性:
cancelBubble => 默认是false,设为true的时候取消事件冒泡(相当于stopPropagation)
returnValue => 默认为true,设为fasle的时候取消事件默认行为(相当于preventDefault)
*************************************************************************************************************************************
在普通浏览器中:
DOM0级和DOM2级事件的相同之处:
事件作用域都是所属元素的作用域内,this指针指向对象本身
不同:
DOM2级可以进行多个执行器的绑定,事件执行顺序根据绑定的先后执行
在IE中:
DOM0级和DOM2级事件的相同:
大概是都可以执行函数吧= =
不同:
DOM2级事件的作用域是全局,this指针指向window。而DOM0级指向元素自身
DOM2级可以绑定多个执行器,但是执行顺序与绑定的顺序相反,放在后面绑定的函数反而先执行
*************************************************************************************************************************************
由于事件流的过程,可以进行事件委托。事件委托不仅可以减少代码量,并且可以优化web性能,不被繁杂的事件委托所拖累。
例如ul中的每一个li都需要绑定一个click事件,就可以对ul绑定click事件,然后判定event.target是否是li,然后进行操作。或者有些li需要不一样的操作,可以用switch进行选择操作