面试题:事件触发过程是什么样的?

浅聊一下

试想一下,我们有三个div,每个div上有一个点击事件,点击最大的div会输出app,点击中间的div会输出wrap,点击最小的div会输出box。那么当我们点击分别点击每一个图层时会输出什么呢?本篇文章将带大家来深入分析一下事件的触发过程...

事件的触发过程

捕获过程

事件触发的第一个过程是捕获过程,在window上往事件触发处传播,遇到注册的捕获事件会触发(从外往内传播)

  • 点击app

点击app,会从window开始往里找,第一步就找到了app,于是输出app

  • 点击wrap

点击wrap,会从window开始往里找,先找到app,再找到wrap,那么我们的输出结果应该是app->wrap 但是结果真的是这样吗?不是, 输出结果为wrap->app

为什么会发生这种情况呢??? 因为在监听器中除了点击事件,触发方法,还有一个可选的参数,参数为布尔值,默认为false

如果第三个参数为true,那么在捕获事件过程捕获到的事件就会触发,如果为false,也就是默认,那就是在冒泡过程触发,所以在这里我们在冒泡过程触发事件,先输出wrap再输出app

js 复制代码
     app.addEventListener('click',(e)=>{//绑定 注册 订阅
        console.log('app');
        e.stopImmediatePropagation()
     },false)
  • 点击box 根据上面两个例子,我们很容易就知道,这里输出顺序为box->wrap->app

那我们来看看什么是冒泡过程

冒泡过程

冒泡过程就是在我们找到目标子容器以后,再向父容器传递的一个过程,也就是捕获事件相反的方向, 从事件触发处往window上传播,遇到注册的冒泡事件会触发

f

event.stopPropagation() || e.stopImmediatePropagation()

如果我只想要我点击的那个容器触发,其他容器不触发,那应该怎么办呢?那么我们就得用到event.stopPropagation()或e.stopImmediatePropagation()了

这两个方法都是用来阻止默认事件的传播(用在冒泡就阻止冒泡,捕获就阻止捕获)

js 复制代码
        let box = document.getElementById('box')
        box.addEventListener('mouseenter',(e)=>{
            console.log('box');
            //  e.stopPropagation()//停止传播
            e.stopImmediatePropagation()
            
        })

此时,我们点击box,就只会打印box

那么这两个方法有什么区别呢?

js 复制代码
        let box = document.getElementById('box')
        box.addEventListener('mouseenter',(e)=>{
            console.log('box');
            //阻止冒泡
            //  e.stopPropagation()//停止传播
            e.stopImmediatePropagation()
            
        })
        box.addEventListener('click',()=>{
            console.log('box2');
               
        })

我们在上面的代码中给box添加了两个点击事件,当我们点击box时,会触发,如果我们使用stopImmediatePropagation()来阻止默认事件的传播,那么我们的监听器只有一个会被触发,也就是mouseenter事件,如果使用 stopPropagation()那么两个事件都会触发...

事件委托

借助冒泡机制,将原本要添加到多个子容器上的事件添加到父容器上

html 复制代码
<!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 id="ul">
        <li>a</li>
        <li>b</li>
        <li>c</li>
        <li>d</li>
        <li>e</li>
    </ul>
    <script>
        let lis = document.querySelectorAll('li')
        lis.forEach((li)=>{
            li.addEventListener('click',()=>{
                console.log(li.innerText);
            })
        })
    </script>
</body>
</html>

如果我们要在ul中的每个li上添加点击事件,按照传统方法,我们可以先获取到每个li,再遍历添加点击事件,但是这种方法属实有一点low了,我们使用在父容器上添加点击事件的方法

js 复制代码
        let ul = document.getElementById('ul')
        ul.addEventListener('click',(e)=>{
            console.log(e.target.innerText);
           
        })

ul 元素上添加了点击事件监听器。当用户点击 ul 元素内部的任意一个子元素时,事件会冒泡到 ul 元素,并触发该监听器。

在监听器中,通过 e.target 可以获取到实际触发事件的元素。通过 e.target.innerText 可以获取到该元素的文本内容。

结尾

祝掘友们新年快乐!!!!!!!!!!

相关推荐
沐爸muba7 分钟前
JS中的for...in和for...of有什么区别?
前端·javascript
lljss20207 分钟前
表格HTML
前端·html
桃花加酥11 分钟前
js笔记(二进制由0和1两个数字组成)
java·javascript
慕仲卿40 分钟前
为什么要使用补码表示负数
javascript
集成显卡41 分钟前
快来用 Rspack/Rsbuild + pnpm 构建你的 monorepo 全栈项目
javascript·webpack·rust
xmh-sxh-13141 小时前
前端常用的主流框架有哪些
前端
程序员大金1 小时前
基于SpringBoot+Vue+MySQL的校园一卡通系统
java·javascript·vue.js·spring boot·后端·mysql·tomcat
NiNg_1_2341 小时前
[Redis面试高频] - zset的底层数据结构
数据结构·redis·面试
m0_528723811 小时前
vue2与vue3的区别
前端·javascript·vue.js
J不A秃V头A1 小时前
el-table使用el-switch选择器没效果
javascript·vue.js·elementui