w3c事件模型中的事件:首先是捕获阶段,达到目标阶段,再进入冒泡阶段。
attachEvent()采用冒泡方式,而addEventListener()可以采用冒泡或事件捕获方式

  1. document.body.addEventListener('click', ()=>{}, true)

image.png

事件冒泡

事件开始的节点元素接收,然后传播至上级

举个栗子
层级关系: document > html > body > div > span > button

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <div onclick="divClick()">
  5. <span onclick="spanClick()">
  6. <button onclick="butClick()">点击</button>
  7. </span>
  8. </div>
  9. </body>
  10. <script>
  11. function butClick() {
  12. console.log('button');
  13. }
  14. function spanClick() {
  15. console.log('span');
  16. }
  17. function divClick() {
  18. console.log('div');
  19. }
  20. document.body.onclick = () => {
  21. console.log('body');
  22. }
  23. </script>
  24. </html>

输出结果
输出顺序: button > span > div > body > html > document
image.png
图片示例:
image.png

事件捕获

上一节点接收事件,然后向下传播到具体节点元素

举个栗子:
层级关系: document > html > body > div > span > button

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <div id="div">
  5. <span id="span">
  6. <button id="button">
  7. 点击
  8. </button>
  9. </span>
  10. </div>
  11. </body>
  12. <script>
  13. const body = document.body;
  14. const div = document.querySelector('div');
  15. const span = document.querySelector('span');
  16. const button = document.querySelector('button');
  17. div.addEventListener('click', (event) => {
  18. console.log('div');
  19. }, true); // false 为冒泡事件、true为捕获事件
  20. span.addEventListener('click', (event) => {
  21. console.log('span');
  22. }, true);
  23. button.addEventListener('click', (event) => {
  24. console.log('button');
  25. }, true);
  26. body.addEventListener('click', (event) => {
  27. console.log('body');
  28. }, true);
  29. </script>
  30. </html>

输出结果
输出顺序: body > div > span > button
image.png
图片示例:
image.png

DOM事件流

事件先是从 捕获事件开始,再到目标事件,最后冒泡事件。

举个栗子:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <div id="div">
  5. <button onclick="buttonClick()">
  6. 点击
  7. </button>
  8. </div>
  9. </body>
  10. <script>
  11. const body = document.body;
  12. const div = document.querySelector('div');
  13. const button = document.querySelector('button');
  14. const buttonClick = (event) => {
  15. console.log('button');
  16. }; // 目标事件
  17. div.addEventListener('click', (event) => {
  18. console.log('div');
  19. }, false); // 冒泡事件
  20. body.addEventListener('click', (event) => {
  21. console.log('body');
  22. }, true); // 捕获事件
  23. </script>
  24. </html>

输出结果:
输出顺序:捕获事件 > 目标事件 > 冒泡事件
image.png

图片示例:
image.png

阻止事件冒泡

w3c模型:调用事件的event.stopPropagation()方法
微软的模型: 设置事件的cancelBubble的属性为true

  1. document.body.addEventListener('click', (event) => {
  2. if(event){
  3. event.stopPropagation();
  4. }else{
  5. window.event.cancelBubble = true;
  6. }
  7. }, false);
  8. // React框架阻止冒泡的方法
  9. const click = (event)=>{
  10. event.nativeEvent.stopImmediatePropagation();
  11. }

举个栗子:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <div id="div">
  5. <button id="button">
  6. 点击
  7. </button>
  8. </div>
  9. </body>
  10. <script>
  11. const body = document.body;
  12. const div = document.querySelector('div');
  13. const button = document.querySelector('button');
  14. button.addEventListener('click', (event) => {
  15. console.log('button');
  16. if(event){
  17. event.stopPropagation();
  18. }else{
  19. window.event.cancelBubble = true;
  20. }
  21. }, false);
  22. div.addEventListener('click', (event) => {
  23. console.log('div');
  24. }, false);
  25. body.addEventListener('click', (event) => {
  26. console.log('body');
  27. }, false);
  28. </script>
  29. </html>

输出结果:
image.png