標籤:
一、事件的捕獲與冒泡
“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。下面這個圖能夠很形象的解釋(理解捕獲和冒泡必不可少的圖)
按照圖我們編寫了代碼去驗證下,
<div id="parent"> <div id="child"> child </div></div><script type="text/javascript"> var p = document.getElementById(‘parent‘), c = document.getElementById(‘child‘); p.addEventListener(‘click‘, function (e) { console.log(‘父節點捕獲‘) }, true); c.addEventListener(‘click‘, function (e) { console.log(‘子節點捕獲‘) }, true); c.addEventListener(‘click‘, function (e) { console.log(‘子節點冒泡‘); }, false); p.addEventListener(‘click‘, function (e) { console.log(‘父節點冒泡‘) }, false);</script>View Code
結果一目瞭然
但是這裡有個問題,也是原來阿里的面試題目,
若是一個dom上綁定了兩次事件,一個捕獲,一個冒泡的,事件執行順序是什麼呢,
這個在參考小鬍子哥的寫js事件機制的部落格中瞭解到,順序是和綁定順序有關係的,那我們來試一下,
<div id="parent" style="height: 300px; background-color: #ccc;"> <div id="child"> child </div> <p>other child</p></div><script type="text/javascript"> var p = document.getElementById(‘parent‘), c = document.getElementById(‘child‘); p.addEventListener(‘click‘, function (e) { console.log(‘父節點冒泡‘) }, false); c.addEventListener(‘click‘, function (e) { console.log(‘子節點冒泡‘); }, false); c.addEventListener(‘click‘, function (e) { console.log(‘子節點捕獲‘) }, true); p.addEventListener(‘click‘, function (e) { console.log(‘父節點捕獲‘) }, true);</script>View Code
當點擊1時
當點擊2時
當點擊3時
我們發現1和3的情況下是先冒泡後捕獲的,代碼中我將冒泡的的綁定事件寫到捕獲前面了,造成了這樣的效果,
事件目的地節點既綁定了冒泡事件也綁定了捕獲事件,此時的執行順序按照綁定的先後順序執行
那第二種為什麼順序是先捕獲後冒泡的呢,是因為事件目的地點 other child沒有綁定事件。
有捕獲和冒泡就有相應的阻止,stopPropagation這個應該是阻止事件的下一步傳播,stopImmediatePropagation這個方法能把綁定在這個元素上的事件都能阻止掉,可以瞭解下。
另附,易混淆的,
event.prevetDefault() => 預設事件event.stopPropogation() => 事件捕獲、事件冒泡,事件代理return false => jquery內部就是調用了上面兩個實現的。二,事件委託機制
對“事件處理常式過多”問題的解決方案就是事件委託,事件委託利用了事件冒泡,只指定一個事件處理常式,就能管理這一類型的所有事件。
比如對ul下的li綁定事件,一般是遍曆li,給每個li綁定事件,這個有兩個問題,1,如果是新加的li,我們需要重新綁定。2,如果li有很多,那佔用記憶體會很多。
那我們這個時候就可以用事件委託了,委託在詞典中解釋,將自己的事務囑託他人代為處理。那就是事件我不放到要處理的dom上面,也就是利用冒泡的原理,將事件綁定到父級上面。再按照每個觸發事件的event對象找到target,說到這,又要說相容問題了,w3c的標準下的,event.target即可,IE的確是event.srcElement。到這我想大家應該會想到一個神器,jQuery了,對的,他裡面的綁定事件都是相容的,都是封裝好的,那他又是怎麼處理的呢,好吧,要去解讀源碼了。
javascript事件機制瞭解與深入