JS事件机制

713 阅读2分钟

事件流

标准事件流会分为三个阶段:事件捕获 => 处于目标阶段 => 事件冒泡阶段。

在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>

优势

  • 事件委托可以显著的提高事件的处理速度,减少内存的占用。
  • 动态新添加的元素同样具有事件处理函数,无需因为元素的改动而修改事件绑定。