天天看點

關于JS中的事件冒泡和事件捕獲

記得剛學JS時老師講的事件冒泡:“魚在水中吐泡泡,是在魚所在的 深水區逐漸上升到水面”。就如這個例子一樣,下面我總結一下我所了解的冒泡和捕獲。

事件冒泡和事件捕獲都是描述事件觸發時序問題的術語,也就是事件流。 (簡單說就是描述在頁面中點選一個按鈕時,是先執行這個節點的事件還是先執行這個節點父節點的事件,的順序。)

事件冒泡

事件冒泡是自上而下的觸發事件,也就是先執行我們觸發的按鈕所綁定的事件,執行完後,接着執行按鈕父元素所綁定的事件。

<div id="one">
    <ul id="two">
        <li id="three">appel<li>
        <li>orange</li>
        <li>pear</li>

    </ul>

</div>
           
var one =document.getElementById('one');
var two=document.getElementById('two');
var three=document.getElementById('three');
    two.addEventListener('click',function(){
       alert('2');
     },false);
    one.addEventListener('click',function(){
       alert('1');
     },false);
    three.addEventListener('click',function(){
       alert('3');
     },false);
           

 注意:這裡的addEventListener方法的第三個參數為false就是事件冒泡,如果是true,就是我們下面要講的事件捕獲。

在這裡如果先點選three,會依次彈出3、2、1,;如果先點選two,會依次彈出2、1;若點選one,隻會彈出1。這就是事件冒泡。

事件捕獲

事件捕獲是和事件冒泡的順序是相反的,也就是說我們把上面的addEventListener方法的第三個參數改為true,那麼

var one =document.getElementById('one');
var two=document.getElementById('two');
var three=document.getElementById('three');
    two.addEventListener('click',function(){
       alert('2');
     },true);
    one.addEventListener('click',function(){
       alert('1');
     },true);
    three.addEventListener('click',function(){
       alert('3');
     },true);
           

現在的結果是:當我點選three的時候,會依次彈出1、2、3,;當我點選two的時候,會依次彈出1、2;當我點選one的時候,隻會彈出1。根據結果可以看出,彈出的順序完全是跟冒泡相反的。

冒泡和捕獲同時存在

如果在上述方法中,同時存在事件冒泡和事件捕獲時,根據W3C的标準,會先執行捕獲在執行冒泡。

如何在日常開發中用到事件冒泡和事件捕獲

在上述HTML代碼中可以看到,如果想實作滑鼠移動到li上時背景變成灰色,就可以用到事件冒泡。

$("one").on("mouseover",function(e){
                $(e.target).css("background-color","#ddd").siblings().css("background-color","white");
            })
           
$("li").on("mouseover",function(){
                $(this).css("background-color","#ddd").siblings().css("background-color","white");
            })
           

上面兩種方法都可以實作,第一種利用了事件冒泡。從代碼量上來看,兩種都差不多,但在執行時第二種比第一種多了周遊li的步驟,而且當動态添加一個li時,第一種是不需要重新綁定方法的,但第二種就要重新綁定了。這裡就要引入另外一個JS中的要點:事件委托(事件代理)。事件委托就是利用事件冒泡的原理來執行的。當點選li時都會冒泡到最外層的div中,那麼隻要給div綁定一個方法,當點選裡面的ul li時也都可以冒泡到最外層的div中,都會觸發執行,這就是事件委托,委托它們的父級代為執行事件。

阻止事件委托和冒泡

上文中的target屬性用來判斷進行點選的元素。e.target表示在事件冒泡中觸發事件的源元素,在IE浏覽器中時e.srcElement。

e.stopPropagation()方法是阻止事件冒泡的,表示到我為止,我父親和祖父的方法就别執行了。

//相容IE

function stopPropagation(e) {  
    if (e.stopPropagation) {  
        e.stopPropagation();  
    } else {  
        window.event.cancelBubble = true;  
    }  
}  
           

繼續閱讀