前端开发:JS的事件冒泡和事件捕获详解

news2024/11/18 7:24:27

前言

在前端开发过程中,关于JS原生的核心内容使用是日常工作中的常态,关于底层和原理的掌握使用,尤其是在性能优化方面甚为重要。作为前端开发的进阶内容,在实际开发过程中事件发生的顺序称为事件流,当触发某个事件的时候会引起一系列的连锁反应,但是当业务场景中页面功能嵌套了某几个元素来处理同一个事件,那么哪个事件会先被触发?这就需要了解事件传播当顺序。也就是当有多个盒子嵌套且多层盒子都存在事件的情况下,需要了解这些事件的发生顺序,JS的事件冒泡和事件捕获就是用来处理事件流中的事件发生顺序的,所以在JS中事件冒泡和事件捕获的使用也是比较常用的知识点,而且在前端求职面试的时候二者也是必考知识点,可以说非常重要,那么本文就来做一下总结,方便查阅使用。

事件流

在介绍事件冒泡和事件捕获之前,首先来了解一下事件流的概念。事件流指的是事件完整执行过程中的流动路径 ,也就是说事件流是网页中元素接受事件的顺序,事件流即事件发生的顺序。事件流分为事件冒泡阶段和事件捕获阶段 ,其中,事件冒泡阶段是从子到父;事件捕获阶段是从父到子。

其实,DOM(文档对象模型)结构是一个树型的结构,当一个HTML元素产生一个事件的时候,该事件会在元素节点与根节点之间的路径上传播,路径所经过的节点都会收到该事件,而这个传播过程的顺序就是DOM事件流。

注意:众所周知,目前前端领域使用的DOM标准事件流传播顺序是按照W3C统一之后的标准,即:先捕获后冒泡,也就是说当触发DOM事件的时候,会先进行事件捕获,捕获到事件源头之后再通过事件传播进行事件冒泡。

addEventListener()方法

在来看一下使用事件冒泡和捕获的时候必用的addEventListener()方法,它其实是一个给事件绑定监听函数的方法,可以接收三个参数,具体如下所示:

element.addEventListener(event, function, useCapture)

其中,第一个参数:event,指的是需要绑定的事件(字符串,指定事件名,不要用on前缀,用click,而不是用onclick);

第二个参数:function,指的是指定事件触发时执行的函数;

第三个参数: useCapture,指的是指定事件流为事件冒泡,默认为false;如果设为true,指定事件流为事件捕获。

注意:addEventListener()方法和原生的“on+事件类型”方法(简称"on()"方法)最大的区别是on()方法会被后面的on()方法覆盖掉,但是addEventListener()方法不会。

事件冒泡

 

在JS中,事件冒泡其实就是事件从目标事件起始,沿着父节点依次向上,且触发父节点上的事件,直至文档根节点。事件发生的顺序就像一个气泡从水底上浮一样:从底到顶、从内到外的顺序,会一直向上,直到水面为止。事件冒泡允许多个操作被集中处理,可以把事件处理器添加到父级元素上,这样可以避免事件处理器添加到多个子级元素上,事件可以在对象层的不同层级中捕获事件。

引申:事件冒泡是由网景公司提出的概念,事件冒泡是从事件源头-->根节点进行事件传播,也就是从内到外的顺序进行事件传播的。

事件冒泡示例

本文分享一个简单的关于事件冒泡的示例,方便理解它的原理,具体代码如下所示:

<template>

<div id="div1">
    first 
  <div id="div2">
        second        
  <div id="div3">		third		</div>
    
 </div>
</div>
</template>

export default {
data(){

	return {}

},

methods: {

    let first = document.getElementById('first');
   
    let second = document.getElementById('second');
   
    let third = document.getElementById('third');
    
    first.addEventListener('click',function(){
        
        console.log("这是first的点击事件");
   
    },false);
    	
    second.addEventListener('click',function(){
        
        console.log("这是second的点击事件");
   
        // event.stopPropagation();   //这就是阻止当前节点事件继续冒泡的方法
    },false);
    
    third.addEventListener('click',function(){
        
        console.log("这是third的点击事件");
    
    },false);
  }

};

输出结果为:

这是third的点击事件

这是second的点击事件

这是first的点击事件

事件捕获

 

在JS中,事件捕获其实就是事件从DOM树最外层开始,依次经过目标节点的各个父级节点,并在这些节点上触发父节点上面的事件,直至到达事件的目标节点为止。

引申:事件捕获是由微软公司提出的概念,事件从根节点(Document 对象)-->事件的目标节点的流向顺序,途中会经过目标节点的各个父级节点,并在这些节点上触发捕获事件,直至到达事件的目标节点。也就是从外到内的顺序进行事件传播的。

事件捕获示例

本文分享一个简单的关于事件捕获的示例,方便理解它的原理,具体代码如下所示:

<template>
 <div id="div1">first
  <div id="div2">second     
    <div id="div3">		third		</div>
  </div>
 </div>
</template>


export default {
data(){
	return {}
},

methods: {

    let first = document.getElementById('first');
   
    let second = document.getElementById('second');
   
    let third = document.getElementById('third');
    
    first.addEventListener('click',function(){
        
        console.log("这是first的点击事件");
   
    },true);
    	
    second.addEventListener('click',function(){
        
        console.log("这是second的点击事件");
  
        // event.stopPropagation();   //这就是阻止当前节点事件继续捕获的方法
    },true);
    
    third.addEventListener('click',function(){
        
        console.log("这是third的点击事件");
    
    },true);
  }

};

输出结果为:

这是first的点击事件

这是second的点击事件

这是third的点击事件

阻止事件捕获和事件冒泡

场景:上面只是介绍了通用的用法,一条线执行,但是实际业务场景并没有这么单一,比如有些时候在某一个节点上绑定了一个事件,但是需要点击时候触发这个事件,可是由于事件冒泡该节点的事件会被其它子元素触发,针对这种情况就需要阻止掉。

针对上面的情况,需要阻止事件冒泡或者事件捕获,在JS中主要是通过使用stopPropagation()方法来阻止,通过使用它可以阻止事件沿着DOM树向上或者向下进行进一步的传播。具体示例代码如下所示:

event.stopPropagation();

也就是直接在相应的处理函数内,加入event.stopPropagation(),终止向上/向下进一步传播,这样事件停留在本节点,不会再往外传播了,完美解决上面的需求点。

事件冒泡和事件捕获同时存在

当同时存在冒泡事件和捕获事件的时候,捕获事件的优先级比冒泡事件的优先级高,且上文已经介绍过,捕获事件是从外到内的,而冒泡事件是从内到外的。具体的代码示例这里就不再演示。

拓展:事件委托

事件委托是利用事件冒泡的原理。 使用情况:当有多个类似的元素需要绑定事件时,一个一个去绑定既浪费时间,又不利于性能,这时候可以使用事件委托,给他们的一个共同父级元素添加一个事件函数去处理所有的事件情况。

<template>
 <ul id="father">
   <li>first</li>
   <li>second</li>
   <li>third</li>
 </ul>
</template>

export default {
data(){
	return {}
},

methods: {
   father.addEventListener("click",function(e){
       if(e.target!=father){
           console.log(`这是${e.target.innerText}的点击事件`)
       }
   });

  }
};

输出结果为:

点击哪个li,就输出"这是哪个li的点击事件"

从上面的示例可以看出,由于采用的是事件冒泡的事件流,所以当点击li元素的时候,向上触发它们的父元素上的点击事件。

这样做的好处就是:提高了性能,不需要循环所有的元素,然后一个个绑定对应的事件;使用灵活,当有新的子元素时不需要再重新绑定事件。

取消冒泡事件:以W3C标准的话,直接使用event.stopPropagation()方法即可,但是IE9以下版本不支持该方法,需要使用scroll、mouseleave、mouseenterfocus、blur、focus、change、submit、reset、select等事件阻止冒泡,但是hover事件不能使用事件委托的方式。

最后

通过本文关于前端开发JS中的事件冒泡和事件捕获的详细介绍,不管是在实际的前端开发工作中还是在前端求职面试中都是非常关键的知识点,所以作为前端开发者来说必须要掌握它相关的内容,尤其是从事前端开发不久的开发者来说尤为重要,是一篇值得阅读的文章,重要性就不在赘述。欢迎关注,一起交流,共同进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序使用 npm 包,举例图文详解

使用 npm 包前提条件&#xff1a; 下载安装&#xff0c;配置npm环境变量&#xff0c;不懂得可以上网查教程&#xff0c;本文不再描述 小程序使用 npm 包简述 1、初始化 package.json 2、勾选允许使用 npm&#xff08;新版微信小程序开发工具忽略这一步&#xff09; 3、下载…

Auto.js的介绍

Auto.js 是一款无需root权限的javascript自动化软件 auto.js是一款安卓手机应用&#xff0c;和微信一样&#xff0c;安装在手机上使用 Auto.is是一款自动化软件&#xff0c;更根据脚本内容便可自动执行相关的操作&#xff0c;并且手机无需root Auto.js的脚本需要使用JavaScri…

Vue中的v-for循环,实现div块的循环生成

前言 大家好,这里是果力成,老规矩,学之!最近在做前端页面遇到一个小问题&#xff0c;说来也不难&#xff0c;但还是花费了我的好些时间&#xff0c;保持习惯记录一下。在前端学习中不免遇到一个div或者一个数组的循环产生&#xff0c;因为挨个儿传数据显然不是最优的。这里讲述…

强大的图片预览组件Viewer.js

​ 1、 Viewer.js简介 Viewer.js 是一款强大的图片查看器。我们通过Viewer.js 在页面上添加强大的图片查看功能&#xff0c;同时&#xff0c;这款优秀的插件配置操作起来也非常的方便。 Viewer.js分为2个版本&#xff0c;js版本和jquery版本&#xff0c;下载地址分别为 纯J…

uniapp组件uni-file-picker中对上传的图片进行压缩至1兆以内

我在做uniapp项目时&#xff0c;用的uni-file-picker组件&#xff0c;这是我做的一个项目实例&#xff0c;主要是将图片通过接口传至后台服务器 如果只是上传一张照片的话 还没有什么大问题&#xff0c;但是如果一连上传很多个图片&#xff0c;像我这个项目一样&#xff0c;而且…

一文搞懂ES6的Map

什么是Map Map是ECMAScript 6 的新增特性&#xff0c;是一种新的集合类型&#xff0c;为javascript带来了真正的键/值存储机 制。 Map 对象存有键值对&#xff0c;其中的键可以是任何数据类型。 Map 对象记得键的原始插入顺序。 Map 对象具有表示映射大小的属性。 Map的基…

海康视频WEB插件 V1.5.2 开发总结

文章目录前言一、效果图二、插件使用步骤总结三、具体步骤分析1.new 一个WebControl 插件实例2.启动插件服务3.创建视频播放窗口、绑定消息回调4.初始化参数&#xff0c;其中secret参数需要通过RSA加密&#xff0c;加密公钥通过WebControl.JS_RequestInterface获取5.通过WebCon…

前端使用html2canvas生成图片踩坑

前端使用html2canvas生成图片经验总结 前言 主要是总结一下html2canvas生成图片的基础用法&#xff0c;以及自己在使用html2canvas过程中踩过的坑和相应的解决思路 背景 近段时间接手一个项目&#xff0c;需要向设备下发某一个图片&#xff0c;为了该图片可以实时更改&…

vue实现tagsview多页签导航功能

文章目录前言一、效果图二、实现思路1. 新建 tags-view.js2. 在Vuex里面引入 tags-view.js3. 新建 tabsView 组件4. 新建 ScrollPane 组件5. 引入 tabsView 组件6. 使用 keep-alive 组件&#xff0c;进行页签的缓存总结前言 基本上后台管理系统都需要有多页签的功能&#xff0…

vue 城市选择器(省市区)的使用 element-china-area-data

一、Element UI 中国省市区级联数据 本文参考&#xff1a;Element UI 中国省市区级联数据 本文参考&#xff1a;根据此文做的整理 1. 安装 npm install element-china-area-data -S2. 使用 import { regionData, CodeToText, TextToCode } from element-china-area-datareg…

vue项目打包优化及配置vue.config.js文件(实测有用)

首先我们需要在根目录里创建一个vue.config.js 首先在文件中先写入 //打包配置文件 module.exports {assetsDir: static, // outputDir的静态资源(js、css、img、fonts)目录publicPath: ./, // 静态资源路径&#xff08;默认/&#xff0c;如果不改打包后会白屏&#x…

HTML樱花飘落

樱花效果 FOR YOU GIRL 以梦为马&#xff0c;不负韶华 LOVE YOU FOREVER 实现代码 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv"…

【JavaScript-动画原理】如何使用js进行动画效果的实现

&#x1f482; 个人主页&#xff1a;Aic山鱼 个人社区&#xff1a;山鱼社区 &#x1f4ac; 如果文章对你有所帮助请点个&#x1f44d;吧!欢迎关注、点赞、收藏(一键三连)和订阅专哦目录 前言 1.动画原理 2.动画函数的封装 3.给不同元素添加定时器 4.缓动动画原理 5.给动…

原生JS实现FlappyBird游戏 超详细解析 快来做一个自己玩吧

目录​ 1.适配设备&#x1f43e; 2.背景滚动&#x1f490; 3.管道的创建与移动&#x1f338; 4.小鸟操作&#x1f337; 5.碰撞检测&#x1f340; 6.触屏事件&#x1f339; 7.制作开始与结束面板&#x1f33b; 8.得分统计&#x1f33a; 我们先来看看接下来我们要做的效果…

vue 路由报错

在进行如下路由跳转时 const edit (index: number) > { let row: any categoryData.value[index]; router.push({ name: “commodityedit”, query: { id: row.id, name: row.name } }); }; 遇到问题如下 TypeError: Failed to fetch dynamically imported module: http…

【uni-app】第三方ui组件推荐引入的方法

ui组件推荐 1. Muse-UI Muse UI 是一套 Material Design 风格开源组件库&#xff0c;旨在快速搭建页面。它基于 Vue 2.0 开发&#xff0c;并提供了自定义主题&#xff0c;充分满足可定制化的需求。material-design-icons 是谷歌定义的一套icontypeface 是谷歌定义的一套字体…

html+css+js制作LOL官网,web前端大作业(3个页面+模拟登录+链接)

文章目录一、效果图1.1首页1.2 模拟登录1.3 游戏资料页面1.4 商城页面二、代码2.1 首页2.2 资料页面2.3 商城页面三、链接一、效果图 1.1首页 1.2 模拟登录 1.3 游戏资料页面 1.4 商城页面 二、代码 2.1 首页 index.html <!doctype html> <html><head>&l…

JavaScript高级 |如何玩转箭头函数?

本文已收录于专栏⭐️ 《JavaScript》⭐️ 学习指南&#xff1a;箭头函数语法规则简写规则常见应用mapfilterreduce箭头函数中的this使用concatthis的查找规则完结散花参考文献箭头函数 在ES6中新增了函数的简写方式----箭头函数&#xff0c;箭头函数的出现不仅简化了大量代码…

Vue3自动引入组件,组件库

在做vue3项目中时&#xff0c;每次使用都需要先进行引入&#xff0c;用ts的还好&#xff0c;会有爆红提示&#xff0c;如果是使用js开发的很多时候都会等到编译的时候才发现哪里哪里又没有引入&#xff0c;就会很浪费时间&#xff0c;偶然发现一款好用的组件可以帮助我们很好的…

【你不知道的 CSS】你写的 CSS 太过冗余,以至于我对它下手了

:is() 你是否曾经写过下方这样冗余的CSS选择器: .active a, .active button, .active label {color: steelblue; }其实上面这段代码可以这样写&#xff1a; .active :is(a, button, label) {color: steelblue; }看~是不是简洁了很多&#xff01; 是的&#xff0c;你可以使用…