事件流
标准事件流会分为三个阶段:事件捕获 => 处于目标阶段 => 事件冒泡阶段。
在IE事件流中:处于目标阶段 => 事件冒泡阶段。
事件捕获阶段是某一事件(各种交互操作)发生时,会从dom树的父级节点开始向子节点层层传递。传递过程中若某一节点注册了该事件的监听函数,便会触发监听函数。
事件监听
//标准事件监听,DOM2级事件处理
相对el.onclick = function(){}来说,1.可以绑定多个同类型事件 2.可以解除事件绑定
element.addEventListener(event, function(event){}, useCapture)
/*event : (必需)事件名,支持所有DOM事件。
function:(必需)指定要事件触发时执行的函数。
useCapture:(可选)指定事件在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。*/
//ie标准:只有事件冒泡阶段
element.attachEvent(event, function)
阻止冒泡
当父节点与子节点都注册了同一个事件的监听函数,且子节点的事件被触发时。冒泡机制会触发父节点上原本并不希望被触发的监听函数。
此时需要在子节点的事件监听里阻止冒泡
function(e){
e.stopPropagation(); //标准
e.cancelBubble=true; //IE
}
事件代理(委托)
场景:一个父节点下有多个子节点,需要为每个子节点添加同一事件监听。
如果对子节点进行循环注册事件:事件处理程序注册过多,与dom节点交互频繁,占用内存。添加新子节点时也要为新的子节点注册事件
解决(事件代理):利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
<ul id="list">
<li id="item1" >item1</li>
<li id="item2" >item2</li>
<li id="item3" >item3</li>
</ul>
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
var list = document.getElementById("list");
//对父元素注册事件,当子节点被点击的时候,click事件会从子节点开始向上冒泡。
父节点捕获到事件之后,通过判断event.target来判断是否为目标子节点,
从而可以获取到相应的信息,并作处理。
list.addEventListener("click",function(event){
var target = event.target;
if(target == item1){
alert(event.target.nodeName);
console.log("hello item1");
}else if(target == item2){
alert(event.target.nodeName);
console.log("hello item2");
}else if(target == item3){
alert(event.target.nodeName);
console.log("hello item3");
}
});
</script>
优势
- 事件委托可以显著的提高事件的处理速度,减少内存的占用。
- 动态新添加的元素同样具有事件处理函数,无需因为元素的改动而修改事件绑定。