1. 程式人生 > >事件冒泡、捕獲和事件委託

事件冒泡、捕獲和事件委託

事件冒泡與捕獲

  1. 事件冒泡:事件從觸發事件的節點開始一直向上傳播直至父節點。
  2. 事件捕獲:事件從父級節點開始一直傳遞到觸發事件的節點。

當你使用事件捕獲時,父級元素先觸發,子級元素後觸發,即div先觸發,p後觸發。
當你使用事件冒泡時,子級元素先觸發,父級元素後觸發,即p先觸發,div後觸發。
IE只支援事件冒泡,Mozilla, Opera 7 和 兩種都支援。
如何決定使用捕獲還是冒泡呢?
(1)一般是利用addEventListener()來繫結事件。
element.addEventListenner(“eventname”,function,boolean)


方法的第三個引數是bool型,如果是TRUE那麼表式採用事件捕獲;若是FALSE,表明是事件冒泡,預設是false。即:
true = 捕獲
false = 冒泡

(2)IE瀏覽器下采用attachEvent()方法,
element.attachEvent(“eventname”,function)

阻止事件冒泡的方法:
W3C中:event.stopPropagation()
IE下設定:cancelBubble=true

DOM事件流有三個階段:事件捕獲、處於目標階段、事件冒泡。
在這裡插入圖片描述

事件委託

只指定一個事件處理程式,將原本子元素上的處理程式委託給父元素執行。如果目標元素上的其他事件處理程式使用了stopPropagation()阻止了事件傳播,那麼事件委託就會失效。

事例:如 ul下有多個li元素時,可以將’li’元素的事件處理程式委託給ul元素,這樣即使後期新增li也無需再去新增事件處理程式了。
click、mousedown、mouseup、keydown、keyup 和 keypress事件可以用事件委託。
下面是事件委託處理的例子。

<ul id="parent">
        <li>item 1</li>
        <li>item 2</li>
        <li>item 3</li>
        <li>item 4</li>
        <li>item 5</li>
        <li>item 6</li>
    </ul>
     <script>
        window.onload = function(){
            var parent = document.getElementById('parent'); //獲取ul元素
             parent.addEventListener('click',function(event){
                var event = event || window.event;  //相容寫法
                var target = event.target || event.srcElement;  //相容屬性寫法
                if(target.nodeName.toLowerCase() == 'li'){
                    alert(target.innerHTML);
                }
            },false)
        }
    </script>

target屬性
定義:event物件有個target屬性,標準瀏覽器下是target,IE瀏覽器是srcElement屬性。target事件屬性可返回事件的目標節點即觸發該事件的節點。
語法:
event.target
event.target.nodeName // 獲取事件觸發元素標籤(如 li、p標籤等)
event.target.[ id /className /innerHTML ]

jQuery中的事件委託方法
自1.7版本後,on()方法代替了bind()、delegate()、live()。
—$ (selector).bind(“click”,function):bind會直接把處理程式繫結到各個元素上,它不能把處理程式繫結到還未存在於頁面中的元素之上。若是新的連結經由AJAX加入到了頁面中,那麼bind處理程式對於這些新加入的連結來說是無效的。
bind缺點:
①它會繫結事件到所有的選出來的元素上,當繫結的元素較多時(如:表格的每個單元格),會查詢和遍歷每個單元格,導致指令碼執行速度明顯變慢;且儲存表格的多個單元格元素和相應的處理程式也會佔用大量記憶體。簡言之:繫結元素較多時,效率低下,佔用記憶體
②. bind只能給呼叫它的時候已經存在的元素繫結事件,不能給未來新增的元素繫結事件,即不能動態繫結到新增的元素上
③. 當頁面載入完的時候,才可以進行bind()

----$ (selector).live(“click”,function)
live缺點:
①. $ ()函式會找到當前頁面中的所有td元素並建立jQuery物件,但在確認事件目標時卻不用這個td元素集合,而是使用選擇符表示式與event.target或其祖先元素進行比較,因而生成這個jQuery物件會造成不必要的開銷
②. 預設把事件繫結到$ (document)元素,如果DOM巢狀結構很深,事件冒泡通過大量祖先元素會導致效能損失,即存在事件傳播鏈過長的問題
③. 只能放在直接選擇的元素後面,不能在連綴的DOM遍歷方法後面使用,即$ (“table td”).live…可以,但$(“table”).find(“td”).live…不行

----$ (selector).delegate(“li”,“click”,function)
----$ (selector).on(“click”,“li”,“function”)

 $(function(){
             $("#parent").on("click","li",function(event){
                 var target = $(event.target);
                target.css("background-color","red");
             })
         })

參考資料:
https://www.cnblogs.com/EnSnail/p/5838630.html