当在一个DOM上,绑定的事件中阻止了冒泡/捕获,那么这个DOM上其他绑定的事件都不会冒泡/捕获了
在线演示
https://jsbin.com/dopohayohu/7/edit?html,css,js,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="out">
<div class="inner"></div>
</div>
</body>
</html>
.out {
width: 200px;
height: 200px;
background: red;
}
.inner {
width: 100px;
height: 100px;
background: green;
}
document.querySelector('.out').addEventListener('click', (event) => {
console.log('out')
})
// document.querySelector('.inner').addEventListener('click', (event) => {
// event.stopPropagation()
// console.log('inner')
// })
document.querySelector('.inner').addEventListener('click', (event) => {
console.log('inner0')
})
document.querySelector('.inner').addEventListener('click', (event) => {
console.log('inner1')
})
document.querySelector('.inner').addEventListener('click', (event) => {
console.log('inner2')
})
document.querySelector('.inner').addEventListener('click', (event) => {
event.stopPropagation()
console.log('inner')
})
由来
根据MDN上的兼容性来看
(function() {
if (!Event.prototype.preventDefault) {
Event.prototype.preventDefault=function() {
this.returnValue=false;
};
}
if (!Event.prototype.stopPropagation) {
Event.prototype.stopPropagation=function() {
// 将当前Event对象的cancelBubble设置为true,在执行完成所有绑定事件回调之后,判断是否冒泡/捕获时,根据此属性标志,不会做冒泡或者捕获处理。
this.cancelBubble=true;
};
}
if (!Element.prototype.addEventListener) {
var eventListeners=[];
var addEventListener=function(type,listener /*, useCapture (will be ignored) */) {
var self=this;
var wrapper=function(e) {
e.target=e.srcElement;
e.currentTarget=self;
if (typeof listener.handleEvent != 'undefined') {
listener.handleEvent(e);
} else {
listener.call(self,e);
}
};
if (type=="DOMContentLoaded") {
var wrapper2=function(e) {
if (document.readyState=="complete") {
wrapper(e);
}
};
document.attachEvent("onreadystatechange",wrapper2);
eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2});
if (document.readyState=="complete") {
var e=new Event();
e.srcElement=window;
wrapper2(e);
}
} else {
this.attachEvent("on"+type,wrapper);
eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper});
}
};
var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) {
var counter=0;
while (counter<eventListeners.length) {
var eventListener=eventListeners[counter];
if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) {
if (type=="DOMContentLoaded") {
this.detachEvent("onreadystatechange",eventListener.wrapper);
} else {
this.detachEvent("on"+type,eventListener.wrapper);
}
eventListeners.splice(counter, 1);
break;
}
++counter;
}
};
Element.prototype.addEventListener=addEventListener;
Element.prototype.removeEventListener=removeEventListener;
if (HTMLDocument) {
HTMLDocument.prototype.addEventListener=addEventListener;
HTMLDocument.prototype.removeEventListener=removeEventListener;
}
if (Window) {
Window.prototype.addEventListener=addEventListener;
Window.prototype.removeEventListener=removeEventListener;
}
}
})();
根据whatwg标准来看
https://dom.spec.whatwg.org/#ref-for-dom-event-stoppropagation
The stopPropagation() method steps are to set this’s stop propagation flag.
https://jsbin.com/rupokisogu/1/edit?js,output
只要绑定事件队列里面有一个执行了event.stopPropagation()
,那么在执行完所有队列中的事件回调之后,不会冒泡或者捕获