JS中的事件冒泡和事件捕獲
談起JavaScript的 事件,事件冒泡、事件捕獲、阻止預設事件這三個話題,無論是面試還是在平時的工作中,都很難避免。
事件捕獲階段:事件從最上一級標籤開始往下查詢,直到捕獲到事件目標(target)。
事件冒泡階段:事件從事件目標(target)開始,往上冒泡直到頁面的最上一級標籤。
1、冒泡事件:
事件按照從最特定的事件目標到最不特定的事件目標(document物件)的順序觸發。通俗來講就是,就是當設定了多個div的巢狀時;即建立了父子關係,當父div與子div共同加入了onclick事件時,當觸發了子div的onclick事件後,子div進行相應的js操作,但是父div的onclick事件同樣會被觸發。
html:
<div>
<input type="button" value="測試事件冒泡" />
</div>
js:
var $input = document.getElementsByTagName("input")[0];
var $div = document.getElementsByTagName("div")[0];
var $body = document.getElementsByTagName("body")[0];
$input.onclick = function(e){
this.style.border = "5px solid red"
var e = e || window.e;
alert("red")
}
$div.onclick = function(e){
this.style.border = "5px solid green"
alert("green")
}
$body.onclick = function(e){
this.style.border = "5px solid yellow"
alert("yellow")
}
效果:依次彈出”red“,"green","yellow"。這就是事件冒泡:觸發button這個元素,卻連同父元素繫結的事件一同觸發。
2、阻止事件冒泡
如果對input的事件繫結改為:
$input.onclick = function(e){
this.style.border = "5px solid red"
var e = e || window.e;
alert("red")
e.stopPropagation();
}
這個時候只會彈出”red“,因為阻止了事件冒泡。
3、事件捕獲:
從頂層元素到目標元素或者從目標元素到頂層元素,和事件冒泡是一個相反的過程。事件從最不精確的物件(document 物件)開始觸發,然後到最精確(也可以在視窗級別捕獲事件,不過必須由開發人員特別指定)。
$input.addEventListener("click", function(){
this.style.border = "5px solid red";
alert("red")
}, true)
$div.addEventListener("click", function(){
this.style.border = "5px solid green";
alert("green")
}, true)
$body.addEventListener("click", function(){
this.style.border = "5px solid yellow";
alert("yellow")
}, true)
這個時候依次彈出”yellow“,"green","red"。這就是事件的捕獲。
如果把addEventListener方法的第三個引數改成false,則表示只在冒泡的階段觸發,彈出的依次為:”red“,"green","yellow"。這是因為在W3C模型中,任何事件發生時,先從頂層開始進行事件捕獲,直到事件觸發到達了事件源元素。然後,再從事件源往上進行事件冒泡,直到到達document。
程式設計師可以自己選擇繫結事件時採用事件捕獲還是事件冒泡,方法就是繫結事件時通過addEventListener函式,它有三個引數,第三個引數若是true,則表示採用事件捕獲,若是false,則表示採用事件冒泡。
ele.addEventListener('click',doSomething2,true)
true=捕獲
false=冒泡