事件冒泡、事件捕捉、事件委託
一:概念
- 事件捕獲指的是從document到觸發事件的那個節點,即自上而下的去觸發事件。
- 事件冒泡剛好相反,是從觸發事件的那個節點一直到document,是自下而上的去觸發事件。
- 事件委託:利用了事件冒泡的原理,在下方通過例項講解
阻止事件委託和冒泡:在事件函式中執行event.stopPropagation()
補充:繫結事件方法(addEventListener)的第三個引數,就是控制事件觸發順序是否為事件捕獲。true,事件捕獲;false,事件冒泡。預設false,即事件冒泡。所以當你對一個dom節點觸發事件時,若外層的節點也設定了相應的事件函式,就會使外層的節點也觸發自己的事件函式。
光看概念,好像明白了,但是在例項中仍然可能判斷錯誤,有可能你的理解就是錯誤的,所以最好自己通過例項測試一下
二:例項講解
事件冒泡和時間捕捉:
<div id="parent">
<div id="child" class="child"></div>
</div>
<script type="text/javascript">
document.getElementById("parent").addEventListener("click",function(e){
console.log("parent事件被觸發," +this.id);
},false);
document.getElementById("child").addEventListener("click",function(e){
console.log("child事件被觸發,"+this.id);
},false);
</script>
上述程式碼給child和parent元素都設定了點選事件,並且都是採用的事件冒泡機制。
1.當點選child元素時,先觸發child的點選事件,再觸發parent的點選事件,列印相應的內容;
2.當點選parent元素時,只觸發parent的點選事件,因為parent元素冒泡上去沒有dom元素設定了click事件的函式;
<div id="parent">
<div id="child" class="child"></div>
</div>
<script type="text/javascript">
document.getElementById("parent").addEventListener("click",function(e){
console.log("parent事件被觸發,"+this.id);
},true);
document.getElementById("child").addEventListener("click",function(e){
console.log("child事件被觸發,"+this.id);
},true);
</script>
上述程式碼採用事件捕捉
1.當點選child元素時,先觸發parent的點選事件,再觸發child的點選事件,列印相應的內容;
2.當點選parent元素時,只觸發parent的點選事件,因為parent元素從上面捕捉下來一直到parent元素沒有dom元素設定了click事件的函式;
總結:所以當點選child元素時,不論是設定的事件捕捉還是事件冒泡,都會觸發parent的點選事件,除非不給parent元素設定點選事件;
事件委託:
當有多個類似的元素需要繫結事件時,一個一個去繫結即浪費時間,又不利於效能,這時候就可以用到事件委託,給他們的一個共同父級元素新增一個事件函式去處理他們所有的事件情況,根據下面程式碼分析;
<ul id="1ist">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<script type="text/javascript">
document.getElementById('1ist').addEventListener('click',function(e){
e.target.innerHTML = "被點選";
});
</script>
可能大家會疑惑,我們並沒有給li分別設定點選函式,為什麼點選相應的li卻會產生效果,我們可以這麼理解,雖然我們沒有給li設定點選事件,但是預設的點選事件是採用的事件冒泡,冒泡到父級元素的點選事件是,用事件的target屬性判斷進行點選的元素
- e.target表示在事件冒泡中觸發事件的源元素,在IE中是e.srcElement
- 並且e.target有很多屬性可以操作
- event.target.nodeName //獲取事件觸發元素標籤name(li,p…)
- event.target.id //獲取事件觸發元素id
- event.target.className //獲取事件觸發元素classname
- event.target.innerHTML //獲取事件觸發元素的內容(li)
然後進行相應操作~~這是我自己理解的。。。如果有錯誤的地方,歡迎在評論中告知(經測試,子元素沒有定義事件函式時,仍然會進行冒泡,觸發父元素的事件函式,並且冒泡和捕捉時,只有相對應 的事件會被觸發,其他不被觸發)
最後展示下e.stopPropagation()的相容寫法(相容IE)
function stopPropagation(e) {
if (e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
}