解密W3C標準冒泡、捕獲機制

在前端開發時,項目經常使用jQuery、zepto作為快速開發的基礎庫,用基礎庫封裝的事件,我們知道這兩個基礎庫都是冒泡機制的事件。

事件機制一般在dom嵌套,並父、子層均綁定事件時需要注意。

這兩個技術說來也簡單,他們是兩種傳播策略而已,一個向上(冒泡),一個向下(捕獲)

思考:為什麼這兩個基礎庫都採用冒泡事件,而不考慮捕獲!

捕獲和冒泡如何相互影響

我們來做幾個任務吧!

有一個前提,#parent為標籤,#child為子標籤,他們是嵌套關係支線任務1

//捕獲模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, true);
//捕獲模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child');
}, true);


結果:
1. parent
2. child
解密W3C標準冒泡、捕獲機制

支線任務2

//捕獲模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, true);
//冒泡模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child');
}, false);

結果:
1. parent
2. child
解密W3C標準冒泡、捕獲機制

支線任務3

//冒泡模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, false);
//捕獲模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child');
}, true);

結果:
1. child
2. parent
解密W3C標準冒泡、捕獲機制

支線任務4

//冒泡模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, false);
//冒泡模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child');
}, false);

結果:
1. child
2. parent
解密W3C標準冒泡、捕獲機制

規律

解密W3C標準冒泡、捕獲機制

【1】從上面的結果得出,父容器的機制確定,子容器的機制不定,結果是確定的,說明父容器影響傳遞;

【2】支線任務1-4是點擊在子容器上,以子容器作為研究對象;

a、如果父容器為捕獲(true)機制,先觸發本身事件,再到子容器;

b、如果父容器為冒泡(false)機制,先觸發子容器事件,再到本身;結論1

【3】在嵌套容器上點擊時,點擊對象是最外層容器;

【4】捕獲機制:本身作為第一個執行參考對象,從本身開始向下傳遞;

【5】冒泡機制:從最底層開始向上傳遞,直至到達本身(二)stopPropagation方法,阻止了什麼?

前提:如果有stopPropagation方法,均放在console方法後面;

有一個假設:

【1】因為stopPropagation是在console後面執行,所以無論何種情況至少出現一個結果;

【2】有4種策略(true + stopPropagation)、(false + stopPropagation)、(true)、(false),也就是說父容器和子容器的排序有16種;

【3】因為假設1,所以結果應該(不確定)有4個分別是(parent、child)、(child、parent)、(parent)、(child);

我們帶著這些假設來做任務。

支線任務5

//捕獲模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent')
e.stopPropagation();
}, true);
//捕獲模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child')
}, true);

結果:
1. parent

這個結果說明,stopPropagation方法會阻止傳遞,無法傳達到子節點上。

所以stopPropagation不是傳聞的阻止冒泡方法,而是阻止傳遞的方法;支線任務6

支線任務6

//冒泡模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent')
e.stopPropagation();
}, false);
//捕獲模式
document.getElementById('child').addEventListener('click', function(e) {
console.log('child')

}, true);
結果:
1. child
2. parent

按照上面的知識儲備,再次論證了結論1

支線任務7

//冒泡模式
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, false);
//捕獲模式
document.getElementById('child').addEventListener('click', function(e) {
e.stopPropagation();
console.log('child');
}, true);

結果:
1. child

子容器觸發了e.stopPropagation(),導致冒泡鏈斷裂,不再向上冒泡,所以#parent沒有被觸發!

支線任務8

//捕獲
document.getElementById('parent').addEventListener('click', function(e) {
console.log('parent');
}, true);
//冒泡
document.getElementById('child').addEventListener('click', function(e) {
console.log('child');
e.stopPropagation();
}, false);


結果:
1. parent
2. child

因為得到了假設2的所有結果,所以不再列舉了,來總結一下!

規律

解密W3C標準冒泡、捕獲機制

這裡進行了[parent,child]、[child,parent]、[parent]、[child] 4種結果,但沒有枚舉,其餘12種排序自己擼一遍,可以更深入瞭解事件機制背後的原理!


總結

通過click事件可以推論,事件的觸發均從最外層觸發(document、html);

事件的執行是先通過機制再通過回調執行;

捕獲機制:本身作為第一個執行參考對象,從本身開始向下傳遞;

冒泡機制:從最底層開始向上傳遞,直至到達本身;

stopPropagation方法不是大家說的阻止冒泡,而是阻止傳遞(捕獲 + 冒泡);


分享到:


相關文章: