天天看点

JavaScript的那些坑之事件代理事件代理事件阶段

JavaScript的事件代理也是前端面试中很容易被问到的题目,因为网上好多的面试题汇总里都出现了js的这个特性。

所以就想总结下这个特性,为了以后不再踩入这个坑。

虽然我还没被面试过,不过下学期就去要找实习辣~祝福我把,咳咳,这都是题外话。

下面进入正题。

事件代理

JavaScript的事件代理也叫事件委托。

通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,

代理呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。

就是利用事件冒泡的原理,把事件加到父级元素上,触发执行效果。从而可以很大程度上来提高执行的效率、而且就算新添加了元素还是会有代理的事件。

假如,我们有一个以下的列表

<ul id="list">
  <li id="item1">item1</li>
  <li id="item2">item2</li>
  <li id="item3">item3</li>
  <li id="item4">item4</li>
  <li id="item5">item5</li>
  <li id="item6">item6</li>
</ul>
           

如果我们想要实现:当鼠标点击某一li时,alert输出该li的内容,最先想到的方法是什么呢?、

很容易大家就会想到:用getElementsByTagName获取li数组对象,然后再循环数组,将每个li都加上点击事件。

但是这种方法存在着很多的弊端,没有顾及到html与JavaScript的分离,所以以后遇到这样的情况,我们就会选择用事件代理来处理。

window.οnlοad=function(){
  var ulNode=document.getElementById("list");
  var liNodes=ulNode.getElementsByTagName("li");
  ulNode.οnclick=function(ev){
    var ev=ev||window.event;
    var target=ev.target||ev.srcElement;
    if(target.nodeName.toLowerCase="li"){
      alert(target.innerHTML); 
    }
  }
}
           

代码很清晰,就是在加载的时候获取的是父元素ul而不是各个li,所以就算li有添加或删除,也不会对上面的代码有丝毫的影响,相比与用循环li数组的方法会好很多。

事件阶段

看完了事件代理的案例之后,再让我们仔细的了解下事件触发的三个阶段:捕获阶段、目标阶段和冒泡阶段。

事件一开始从文档的根节点流向目标对象(捕获阶段),然后在目标对向上被触发(目标阶段),之后再回溯到文档的根节点(冒泡阶段)。

(图片来自网络)

JavaScript的那些坑之事件代理事件代理事件阶段

事件捕获阶段(Capture Phase)

事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达时间的目标节点。捕获阶段的主要任务是简历传播路径,在冒泡阶段,时间会通过这个路径回溯到文档根节点。

目标阶段(Target Phase)

当事件到达目标节点时,事件就进入了目标阶段。事件在目标节点上被触发,然后逆向回流,知道传播到最外层的文档节点。

对于多层嵌套的节点,鼠标和指针事件经常会被定位到最里层的元素上。假设,你在一个div元素上设置了click的监听函数,而用户点击在了这个div元素内部的p元素上,那么p元素就是这个时间的目标元素。事件冒泡让我们可以在这个div或者更上层的元素上监听click事件,并且时间传播过程中触发回调函数。

冒泡阶段(Bubble Phase)

事件在目标事件上触发后,并不在这个元素上终止。它会随着DOM树一层层向上冒泡,直到到达最外层的根节点。也就是说,同一事件会一次在目标节点的父节点,父节点的父节点...直到最外层的节点上触发。

在捕获阶段和冒泡阶段还存在着事件监听,以后有机会再继续总结把~