说说事件委托

事件委托,说白了就是本来你要给一个元素添加一个事件(比如点击),出于某些考率,现在要把事件添加给它的外层元素。

事件源

解释事件委托之前,应该先了解下事件源。简单来说,事件源就是直接触发事件的元素。在事件函数中可通过event对象的target属性访问事件源。

看一个例子:

图中,单击span部分,控制台会打印出对应span元素;单击span外的p部分,会打印出对应p元素;单击p外的div部分,会打印出对应div元素。

关键代码如下:

 1     <body>
 2         <div id="box">div
 3             <p>p
 4                 <span>span</span>
 5             </p>
 6         </div>
 7     </body>    
 8     <script>
 9         window.onload=function(){
10             var box=document.getElementById("box");
11             box.onclick=function(ev){
12                 console.log((ev || window.event).target);
13             };
14     </script>

事件委托

再说事件委托。通常,我们用事件委托解决两问题:1、避免不必要的性能开销;2 、新生成的元素不需要重新添加事件。

先看一个经典的例子:

例子中,我们希望点击li能打印对应的文本。

 1     <body>    
 2         <ul id="list">
 3             <li>red</li>
 4             <li>green</li>
 5             <li>blue</li>
 6             <li>pink</li>
 7             <li>black</li>
 8         </ul>
 9     </body>
10     <script>
11         var list=document.getElementById("list");
12         var lis=document.querySelectorAll("li");
13         
14         for(var i=0;i<lis.length;i++){
15             lis[i].onclick=function(){
16                 console.log(this.firstChild.nodeValue);   //本来单击li,可以打印出其对应文本
17             };
18         }
19         
20         list.innerHTML+='<li>yellow</li>';   //这里加了一行后,单击li就无法打印出li对应文本了    
21     </script>    

本来,单击li是可以在控制台打印对应文体的。但是,现在20行加了一行代码,单击li就无法打印出li对应文本了。因为innerHTML会将原有内容全部清空,再赋予新内容,所以li绑定的单击事件也将失效。类似这种情况的还有,使用cloneNode(),新节点不会复制源节点的事件;jQuery中通过remove()移除的节点,重新添加回来后,之前绑定的事件将失效。(PS:detach()在这点上与remove()不同。)

下面,我将上面代码中的for循环换成以下代码:

1              list.onclick = function(ev){
2                  var ev = ev || window.event;
3                  if(ev.target.tagName.toLowerCase()=='li'){
4                      console.log(ev.target.innerHTML);    //单击li,即事件源是li是打印出其对应文本
5                  }
6              };

这样就解决了刚才遇到的问题,而且避免了使用for循环。其实,在这个解决方案中,我们是把点击事件绑定在了li的父级元素ul身上,也就是所谓的事件委托。然后对事件源进行判断,等于间接地给li添加了点击事件。

   

知识共享许可协议
本作品采用知识共享署名 4.0 国际许可协议进行许可。

posted @ 2017-03-15 12:26  Francis_Li  阅读(336)  评论(0编辑  收藏  举报