面试题:浅谈JS中的事件流和事件委托

默认行为

JavaScript 中的事件流描述了在触发事件时,事件是如何在 DOM 中传播和处理的过程。事件流分为三个阶段:捕获阶段、目标阶段和冒泡阶段。

  • 捕获阶段:事件从window上往事件触发处传播,遇到注册的捕获事件会触发(捕获过程)。在捕获阶段中,事件首先被顶层元素捕获,然后逐级向下传播,直到达到事件的目标元素。
  • 目标阶段:事件传播到目标处时的阶段。在目标阶段中,事件被目标元素上绑定的事件处理函数捕获并执行。
  • 冒泡阶段:从事件触发处往window上传播, 遇到注册的冒泡事件就会触发。在冒泡阶段中,事件会从目标元素开始逐级向上冒泡,直到达到顶层元素。

阻止默认行为的方法

  • event.stopPropagation()------可以阻止事件流的传播
javascript 复制代码
document.getElementById("childElement").addEventListener("click", function(event) {
    event.stopPropagation();
    // ...
  });

用于阻止事件继续传播,即停止事件的捕获或冒泡过程。这意味着,在调用该方法后,事件将不会再被传递给其他元素,而是直接停止在当前元素上。当在事件处理函数中调用此方法时,它会立即停止事件在 DOM 树中的传播,即停止事件的捕获和冒泡阶段。

  • event.stopImmediatePropagation()------可以阻止事件流的传播的同时可以阻止同一个容器上绑定其他相同事件
javascript 复制代码
document.getElementById("myLink").addEventListener("click", function(event) {
    event.preventDefault();
    // ...
  });

具体地说,有些交互操作会触发浏览器默认的行为,例如点击链接会跳转到新页面,提交表单会刷新页面等。可以在事件处理函数中使用该方法来取消默认行为。


事件委托

事件委托是一种常用的前端开发技巧,其核心思想是将事件绑定到一个父元素上,然后利用事件冒泡机制,让父元素代替子元素执行事件处理函数。

通常情况下,我们会为每个需要绑定事件的子元素都单独绑定一个事件处理函数。但是,当子元素数量很多时,这种方式会导致性能问题,因为每次事件触发都要执行大量的事件处理函数。

而事件委托可以通过让父元素代理处理所有子元素的事件来解决这个问题。例如,在一个列表中,需要为每个列表项绑定单击事件,可以将事件绑定在列表元素的父级元素上:

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
  </ul>

  <!-- <script> //在li上绑定事件处理函数
    // 点哪一个li,就log出它的内容
    let lis = document.getElementsByTagName('li')
    // lis.__proto__.forEach = Array.prototype.forEach
    Array.from(lis).forEach(li => {
      li.addEventListener('click', () => {
        console.log(li.innerHTML);
      })
    });
  </script> -->
  <script> //在父元素上绑定事件处理函数
    let ul = document.getElementsByTagName('ul')[0]
    ul.addEventListener('click', (event) => {
      // 此时事件流从哪里来到了ul上
      console.log(event.target.innerHTML);
    })
  </script>
</body>
</html>
相关推荐
没有bug.的程序员3 小时前
JAVA面试宝典 - 《MyBatis 进阶:插件开发与二级缓存》
java·面试·mybatis
工业甲酰苯胺3 小时前
TypeScript枚举类型应用:前后端状态码映射的最简方案
javascript·typescript·状态模式
brzhang3 小时前
我操,终于有人把 AI 大佬们 PUA 程序员的套路给讲明白了!
前端·后端·架构
止观止3 小时前
React虚拟DOM的进化之路
前端·react.js·前端框架·reactjs·react
goms3 小时前
前端项目集成lint-staged
前端·vue·lint-staged
谢尔登3 小时前
【React Natve】NetworkError 和 TouchableOpacity 组件
前端·react.js·前端框架
Lin Hsüeh-ch'in4 小时前
如何彻底禁用 Chrome 自动更新
前端·chrome
augenstern4165 小时前
HTML面试题
前端·html
张可5 小时前
一个KMP/CMP项目的组织结构和集成方式
android·前端·kotlin
顾林海6 小时前
Android 性能优化:启动优化全解析
android·java·面试·性能优化·zygote