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

浅聊一下

试想一下,我们有三个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 可以获取到该元素的文本内容。

结尾

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

相关推荐
浪裡遊几秒前
TypeScript中的函数类型定义与类型约束
javascript·ubuntu·typescript
camellia1 分钟前
SpringBoot(二十四)SpringBoot集成redis哨兵集群
java·前端·后端
YH丶浩4 分钟前
React 实现爱心花园动画
前端·react.js·前端框架
啵啵学习11 分钟前
浏览器插件,提示:此扩展程序未遵循 Chrome 扩展程序的最佳实践,因此已无法再使用
前端·chrome·浏览器·插件·破解
Mintopia17 分钟前
# 使用 Three.js 实现带随机障碍物的小车行驶模拟
前端·javascript·three.js
Mintopia18 分钟前
图形学与坐标系入门教学
前端·javascript·计算机图形学
Goboy26 分钟前
开发者必读的日志管理技巧
后端·面试·架构
猿java33 分钟前
什么是Nginx?它有哪些应用场景?
java·nginx·面试
独立开阀者_FwtCoder34 分钟前
8年磨一剑,Koa 3.0 正式发布!看看带来了哪些新功能
前端·javascript·后端
Frankabcdefgh40 分钟前
初中级前端面试全攻略:自我介绍模板、项目讲解套路与常见问答
前端·面试·职场和发展