面试题:浅谈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>
相关推荐
飞翔的佩奇11 分钟前
【完整源码+数据集+部署教程】【天线&水】舰船战舰检测与分类图像分割系统源码&数据集全套:改进yolo11-repvit
前端·python·yolo·计算机视觉·数据集·yolo11·舰船战舰检测与分类图像分割系统
哆啦A梦15881 小时前
点击Top切换数据
前端·javascript·vue.js
程序猿追1 小时前
Vue组件化开发
前端·html
艾德金的溪2 小时前
redis-7.4.6部署安装
前端·数据库·redis·缓存
小光学长2 小时前
基于Vue的2025年哈尔滨亚冬会志愿者管理系统5zqg6m36(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
@PHARAOH2 小时前
WHAT - 受控组件和非受控组件
前端·javascript·react.js
生莫甲鲁浪戴2 小时前
Android Studio新手开发第二十六天
android·前端·android studio
JH30733 小时前
B/S架构、HTTP协议与Web服务器详解
前端·http·架构
yi碗汤园3 小时前
【超详细】C#自定义工具类-StringHelper
开发语言·前端·unity·c#·游戏引擎
怪兽20144 小时前
Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么?
android·面试