天天看點

DOM事件流詳解事件流相關概念  事件捕獲事件冒泡事件委托

目錄

        事件流相關概念  

        事件捕獲

        事件冒泡

        事件委托

        優點

        缺點

事件流相關概念  

        事件流描述的是從頁面中接受事件的順序

        DOM事件流包括三個階段:

        1.事件捕獲階段:事件從window對象開始觸發,該階段主要捕獲截取事件

        2.處于目标階段:該階段具有雙重範圍--捕獲階段結束、冒泡階段開始

        3.事件冒泡階段:将目标元素綁定事件執行結果傳回給浏覽器

DOM事件流詳解事件流相關概念  事件捕獲事件冒泡事件委托

事件捕獲

        該概念由網景公司提出。事件響應從最外層window開始,逐級向内層傳播,直到具體的事件目标元素。

        在上一篇總結事件處理的部落格中,我們有了解到使用事件監聽方式給元素注冊事件處理函數,其中第三個可選參數capture,預設false(事件冒泡階段處理),可填true(事件捕獲階段處理),通過這個參數我們就可以設定事件處理階段采用什麼方式。現在我們可以通過代碼測試來看看事件捕獲與事件冒泡之間的差別:

<div>
        <p>
            <button>點選</button>
        </p>
    </div>
    <script>
        var div = document.querySelector('div');
        var p = document.querySelector('p');
        var button = document.querySelector('button');
        //注冊捕獲事件監聽器
        div.addEventListener('click',function(e){
            console.log("div元素");
        },true);
        p.addEventListener('click',function(e){
            console.log("p元素");
        },true);
        button.addEventListener('click',function(e){
            console.log("button元素");
        },true);
    </script>
           

        點選按鈕後console調試接口中各個輸出順序如下:可見是由外到内逐個捕獲 

DOM事件流詳解事件流相關概念  事件捕獲事件冒泡事件委托

事件冒泡

        該概念由微軟公司提出,事件傳播順序與事件捕獲相反,是從事件按開始的具體元素,一級級往上傳播,直至傳回給window。

        例如:

<div>
        <p>
            <button>點選</button>
        </p>
    </div>
    <script>
        var div = document.querySelector('div');
        var p = document.querySelector('p');
        var button = document.querySelector('button');
        //注冊冒泡事件監聽器
        div.addEventListener('click',function(e){
            console.log("div元素");
        },false);
        p.addEventListener('click',function(e){
            console.log("p元素");
        },false);
        button.addEventListener('click',function(e){
            console.log("button元素");
        },false);
    </script>
           

        點選按鈕後console調試接口中各個輸出順序如下:可見是由内到外逐個捕獲  

DOM事件流詳解事件流相關概念  事件捕獲事件冒泡事件委托

事件委托

        事件委托,也稱事件代理,利用它将事件綁定給父級元素或者更進階元素,讓處理代碼在父級元素或者更進階元素中執行,這樣隻指定一個事件處理程式,就可以管理某一類型的所有事件,提高程式運作效率。舉個例子:一個班的教材,每個人自己去教材科領書會很繁雜,很導緻很多人排隊進度慢,利用事件委托,讓班主任領回全班的書再依次分發給同學們,這樣就會提高效率,減少不必要的程序。

        例如,我們想給每個<li>綁定單擊事件,正常方法是使用周遊給每個<li>綁定一個單擊事件

<ul>
        <li>content1</li>
        <li>content2</li>
        <li>content3</li>
        <li>content4</li>
        <li>content5</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        for(var i=0;i<lis.length;i++){
            lis[i].onclick = function(){
                console.log(this.innerText);
            }
        }
    </script>
           

        這個方法在清單項少的時候可以使用,但是當清單項很多的時候,例如成千上萬個<li>,就會導緻性能降低。這個時候我們利用事件委托,隻需要給<ul>綁定一個事件:

<ul>
        <li>content1</li>
        <li>content2</li>
        <li>content3</li>
        <li>content4</li>
        <li>content5</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        ul.addEventListener("click",function(e){
            var e = e || window.event;  //相容性處理
            if(e.target.nodeName.toLowerCase() === 'li'){
                console.log(e.target.innerText);
            }},false);
    </script>
           

        它的原理是利用了事件冒泡機制,當點選<li>,會向上冒泡到<ul>,然後就會觸發綁定在<ul>上的事件,再利用event.target屬性找到觸發時間的節點,做出相應動作,就可以達到相同的效果。

        使用事件代理不僅可以将多個事件處理函數減少為一個,還可以針對不同的元素做出不同的處理方法。例如上例中,若清單元素中添加其他元素節點,我們可以直接修改事件代裡的事件處理函數,用此來代替循環給元素綁定事件。

        綜上我們可以總結一下事件委托的優缺點:

優點

        1.減少事件注冊,節省記憶體占用

        2.動态綁定事件,當新增子對象時無需再次對其綁定

缺點

        1.如果DOM嵌套結構很深,事件冒泡通過大量祖先元素會導緻性能損失

        2.事件冒泡過程也需要耗時,越靠近頂層,事件傳播鍊越長,耗時越長(是以使用事件委托時,不是把事件委托給的元素越靠近頂層越好,需要根據代碼要實作的效果均衡考慮)

繼續閱讀