徹底弄懂JS的事件冒泡和事件捕獲(不推薦閱讀)


由於搬去敵台了,好久沒來博客園,今天無意中翻到有“誤認子弟”的評論,這里特意做個說明。

本文中關於事件冒泡和事件捕獲的描述和例子都是OK的,錯就錯在后面用jquery去展示了利用事件冒泡的例子有誤,其實這部分就是“事件委托”,而當時的我並不知道,這一點在我很久之前的評論中糾正過。

歸根結底,是當時的我對dom事件這個東西沒有一個系統的認識。事件模型、事件流、event對象、事件代理/委托、甚至自定義事件,加起來才是dom事件的全貌,都理解了才能徹底弄懂。本想刪除了事,但抱着尊重歷史的態度(其實是我不舍得刪,畢竟是我的第一篇博文),特意在標題中標明:不推薦閱讀。

最后,對被“毒害”了的萌新和讀者們表示最真摯的歉意,抱歉!請大家原諒那個當初年幼無知的我!

---------以上為2019.2.13更新---------------

在學校,聽老師講解事件冒泡和事件捕獲機制的時候跟聽天書一樣,只依稀記得IE使用的是事件冒泡,其他瀏覽器則是事件捕獲。當時的我,把它當成IE瀏覽器兼容問題,所以沒有深究(IE8以下版本的瀏覽器已基本退出市場)。工作至今,雖然多次遇到該類問題,但均未深究,始終一知半解,遇到了全TM靠猜(選A不行就選B唄)。今天閑來無事自己做了個demo,算是把這個問題徹底搞明白了。

先上結論:他們是描述事件觸發時序問題的術語。事件捕獲指的是從document到觸發事件的那個節點,即自上而下的去觸發事件。相反的,事件冒泡是自下而上的去觸發事件。綁定事件方法的第三個參數,就是控制事件觸發順序是否為事件捕獲。true,事件捕獲;false,事件冒泡。默認false,即事件冒泡。Jquery的e.stopPropagation會阻止冒泡,意思就是到我為止,我的爹和祖宗的事件就不要觸發了。

這是HTML結構

        <div id="parent">
          <div id="child" class="child"></div>
        </div>

現在我們給它們綁定上事件

            document.getElementById("parent").addEventListener("click",function(e){
                alert("parent事件被觸發,"+this.id);
            })
            document.getElementById("child").addEventListener("click",function(e){
                alert("child事件被觸發,"+this.id)
            })

結果:

child事件被觸發,child
parent事件被觸發,parent

結論:先child,然后parent。事件的觸發順序自內向外,這就是事件冒泡。

現在改變第三個參數的值為true

       document.getElementById("parent").addEventListener("click",function(e){
                alert("parent事件被觸發,"+e.target.id);
            },true)
            document.getElementById("child").addEventListener("click",function(e){
                alert("child事件被觸發,"+e.target.id)
            },true)

結果:

parent事件被觸發,parent
child事件被觸發,child

結論:先parent,然后child。事件觸發順序變更為自外向內,這就是事件捕獲。

貌似沒什么卵用,上一個利用事件冒泡的案例,反正我是經常會用到。

    <ul>
            <li>item1</li>
            <li>item2</li>
            <li>item3</li>
            <li>item4</li>
            <li>item5</li>
            <li>item6</li>
        </ul>

需求是這樣的:鼠標放到li上對應的li背景變灰。

利用事件冒泡實現:

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

也許有人會說,我們直接給所有li都綁上事件也可以啊,一點也不麻煩,只要……

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

是,這樣也行。而且從代碼簡潔程度上,兩者是相若仿佛的。但是,前者少了一個遍歷所有li節點的操作,所以在性能上肯定是更優的。

還有就是,如果我們在綁定事件完成后,頁面又動態的加載了一些元素……

$("<li>item7</li>").appendTo("ul");

這時候,第二種方案,由於綁定事件的時候item7還不存在,所以為了效果,我們還要給它再綁定一次事件。而利用冒泡方案由於是給ul綁的事件……

高下立判!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM