在前端開發時,項目經常使用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
支線任務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
支線任務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
支線任務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
規律
【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的所有結果,所以不再列舉了,來總結一下!
規律
這裡進行了[parent,child]、[child,parent]、[parent]、[child] 4種結果,但沒有枚舉,其餘12種排序自己擼一遍,可以更深入瞭解事件機制背後的原理!
總結
通過click事件可以推論,事件的觸發均從最外層觸發(document、html);
事件的執行是先通過機制再通過回調執行;
捕獲機制:本身作為第一個執行參考對象,從本身開始向下傳遞;
冒泡機制:從最底層開始向上傳遞,直至到達本身;
stopPropagation方法不是大家說的阻止冒泡,而是阻止傳遞(捕獲 + 冒泡);
閱讀更多 JS加加網 的文章