当在一个DOM上,绑定的事件中阻止了冒泡/捕获,那么这个DOM上其他绑定的事件都不会冒泡/捕获了

在线演示

https://jsbin.com/dopohayohu/7/edit?html,css,js,output

关于DOM事件,阻止冒泡/捕获的冷知识 - 图1

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width">
  6. <title>JS Bin</title>
  7. </head>
  8. <body>
  9. <div class="out">
  10. <div class="inner"></div>
  11. </div>
  12. </body>
  13. </html>
  1. .out {
  2. width: 200px;
  3. height: 200px;
  4. background: red;
  5. }
  6. .inner {
  7. width: 100px;
  8. height: 100px;
  9. background: green;
  10. }
  1. document.querySelector('.out').addEventListener('click', (event) => {
  2. console.log('out')
  3. })
  4. // document.querySelector('.inner').addEventListener('click', (event) => {
  5. // event.stopPropagation()
  6. // console.log('inner')
  7. // })
  8. document.querySelector('.inner').addEventListener('click', (event) => {
  9. console.log('inner0')
  10. })
  11. document.querySelector('.inner').addEventListener('click', (event) => {
  12. console.log('inner1')
  13. })
  14. document.querySelector('.inner').addEventListener('click', (event) => {
  15. console.log('inner2')
  16. })
  17. document.querySelector('.inner').addEventListener('click', (event) => {
  18. event.stopPropagation()
  19. console.log('inner')
  20. })

由来

根据MDN上的兼容性来看

  1. (function() {
  2. if (!Event.prototype.preventDefault) {
  3. Event.prototype.preventDefault=function() {
  4. this.returnValue=false;
  5. };
  6. }
  7. if (!Event.prototype.stopPropagation) {
  8. Event.prototype.stopPropagation=function() {
  9. // 将当前Event对象的cancelBubble设置为true,在执行完成所有绑定事件回调之后,判断是否冒泡/捕获时,根据此属性标志,不会做冒泡或者捕获处理。
  10. this.cancelBubble=true;
  11. };
  12. }
  13. if (!Element.prototype.addEventListener) {
  14. var eventListeners=[];
  15. var addEventListener=function(type,listener /*, useCapture (will be ignored) */) {
  16. var self=this;
  17. var wrapper=function(e) {
  18. e.target=e.srcElement;
  19. e.currentTarget=self;
  20. if (typeof listener.handleEvent != 'undefined') {
  21. listener.handleEvent(e);
  22. } else {
  23. listener.call(self,e);
  24. }
  25. };
  26. if (type=="DOMContentLoaded") {
  27. var wrapper2=function(e) {
  28. if (document.readyState=="complete") {
  29. wrapper(e);
  30. }
  31. };
  32. document.attachEvent("onreadystatechange",wrapper2);
  33. eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2});
  34. if (document.readyState=="complete") {
  35. var e=new Event();
  36. e.srcElement=window;
  37. wrapper2(e);
  38. }
  39. } else {
  40. this.attachEvent("on"+type,wrapper);
  41. eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper});
  42. }
  43. };
  44. var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) {
  45. var counter=0;
  46. while (counter<eventListeners.length) {
  47. var eventListener=eventListeners[counter];
  48. if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) {
  49. if (type=="DOMContentLoaded") {
  50. this.detachEvent("onreadystatechange",eventListener.wrapper);
  51. } else {
  52. this.detachEvent("on"+type,eventListener.wrapper);
  53. }
  54. eventListeners.splice(counter, 1);
  55. break;
  56. }
  57. ++counter;
  58. }
  59. };
  60. Element.prototype.addEventListener=addEventListener;
  61. Element.prototype.removeEventListener=removeEventListener;
  62. if (HTMLDocument) {
  63. HTMLDocument.prototype.addEventListener=addEventListener;
  64. HTMLDocument.prototype.removeEventListener=removeEventListener;
  65. }
  66. if (Window) {
  67. Window.prototype.addEventListener=addEventListener;
  68. Window.prototype.removeEventListener=removeEventListener;
  69. }
  70. }
  71. })();

根据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(),那么在执行完所有队列中的事件回调之后,不会冒泡或者捕获

结束