天天看點

說說事件委托

事件委托,說白了就是本來你要給一個元素添加一個事件(比如點選),出于某些考率,現在要把事件添加給它的外層元素。

事件源

解釋事件委托之前,應該先了解下事件源。簡單來說,事件源就是直接觸發事件的元素。在事件函數中可通過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 國際許可協定進行許可。