面试题:浅谈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>
相关推荐
花花鱼1 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k09335 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang135826 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning26 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
时差95330 分钟前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
web行路人36 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00137 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙