面试题:浅谈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>
相关推荐
longze_73 小时前
Vue中:deep()和 ::v-deep选择器的区别
前端·javascript·vue.js
太阳伞下的阿呆6 小时前
本地环境vue与springboot联调
前端·vue.js·spring boot
无限大66 小时前
只出现一次的数字:从暴力美学到位运算神技的进化之路
后端·面试
阳光是sunny6 小时前
走进微前端(1)手写single-spa核心原理
前端·javascript·vue.js
烛阴7 小时前
Ceil -- 从平滑到阶梯
前端·webgl
90后的晨仔7 小时前
🔍Vue 模板引用(Template Refs)全解析:当你必须操作 DOM 时
前端·vue.js
90后的晨仔7 小时前
👂 Vue 侦听器(watch)详解:监听数据的变化
前端·vue.js
90后的晨仔8 小时前
深入浅出 Vue 的 computed:不仅仅是“计算属性”那么简单!
前端·vue.js
Nan_Shu_6148 小时前
学习:入门uniapp Vue3组合式API版本(17)
前端·vue.js·学习·uni-app
程序员曦曦8 小时前
15:00开始面试,15:06就出来了,问的问题有点变态。。。
自动化测试·软件测试·功能测试·程序人生·面试·职场和发展