摘抄
當一個DOM事件被觸發時,它不僅僅只是單純地在本身對象上觸發一次,而是會經歷三個不同的階段:
- 捕獲階段:先由文檔的根節點document往事件觸發對象,從外向內捕獲事件對象;
- 目標階段:到達目標事件位置(事發地),觸發事件;
- 冒泡階段:再從目標事件位置往文檔的根節點方向回溯,從內向外冒泡事件對象。
來源:https://blog.csdn.net/ywl570717586/article/details/70888020
正文
綁定在被點擊元素的事件是按照代碼順序發生,其他元素通過冒泡或者捕獲“感知”的事件,按照W3C的標準,先發生捕獲事件,後發生冒泡事件。所有事件的順序是:其他元素捕獲階段事件 -> 本元素代碼順序事件 -> 其他元素冒泡階段事件 。
addEventListener函數的第三個參數設置爲true爲捕獲事件,false爲冒泡事件。
<body οnlοad="load();">
<div id="d1" style="width: 400px; height: 400px; border: solid 1px;">
<div id="d2" style="width: 200px; height: 200px; border: solid 1px;">
<div id="d3" style="width: 100px; height: 100px; border: solid 1px;">one</div>
</div>
</div>
</body>
栗子1(捕獲)
<script type="text/javascript">
function load() {
div1 = document.getElementById("d1");
div2 = document.getElementById("d2");
div3 = document.getElementById("d3");
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於捕獲階段");
}, true);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於捕獲階段");
}, true);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於捕獲階段");
}, true);
}
</script>
點擊div3
栗子2(冒泡)
<script type="text/javascript">
function load() {
div1 = document.getElementById("d1");
div2 = document.getElementById("d2");
div3 = document.getElementById("d3");
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於冒泡階段");
}, false);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於冒泡階段");
}, false);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於冒泡階段");
}, false);
}
</script>
點擊div3
栗子3(組合,先設置捕獲,後設置冒泡)
<script type="text/javascript">
function load() {
div1 = document.getElementById("d1");
div2 = document.getElementById("d2");
div3 = document.getElementById("d3");
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於捕獲階段");
}, true);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於捕獲階段");
}, true);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於捕獲階段");
}, true);
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於冒泡階段");
}, false);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於冒泡階段");
// e.stopImmediatePropagation();
}, false);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於冒泡階段");
}, false);
}
</script>
點擊div3 ,div1和div2不是真正被點擊的目標元素,按照先捕獲後冒泡順序執行。div1和div2的捕獲函數執行以後,輪到div3觸發事件的時候,因爲代碼中先設置的捕獲監聽,後設置的冒泡監聽,所以先觸發了捕獲函數的執行。
栗子4(組合,先設置冒泡,後設置捕獲)
<script type="text/javascript">
function load() {
div1 = document.getElementById("d1");
div2 = document.getElementById("d2");
div3 = document.getElementById("d3");
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於冒泡階段");
}, false);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於冒泡階段");
}, false);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於冒泡階段");
}, false);
div1.addEventListener("click", (e) => {
console.log("div1被點擊,監聽觸發於捕獲階段");
}, true);
div2.addEventListener("click", (e) => {
console.log("div2被點擊,監聽觸發於捕獲階段");
}, true);
div3.addEventListener("click", (e) => {
console.log("div3被點擊,監聽觸發於捕獲階段");
}, true);
}
</script>
點擊div3 ,div1和div2不是真正被點擊的目標元素,按照先捕獲後冒泡順序執行。div1和div2的捕獲函數執行以後,輪到div3觸發事件的時候,因爲代碼中先設置的冒泡監聽,後設置的捕獲監聽,所以先觸發了冒泡函數的執行。