vue跟jQuery中的事件冒泡、事件捕获、事件委托(事件代理)

devtools/2024/9/25 3:34:24/

1、事件捕获、事件冒泡

在JS中,我们管事件发生的顺序叫“事件流”

标准的事件流:当dom触发了事件后,会先通过事件传播捕获到目标元素,然后目标节点通过事件传播实现事件冒泡

事件传播:无论是捕获还是冒泡,都是靠事件传播一层一层传递的,当在某一层禁止事件传播,那么之后的步骤就不再进行了

Tips:目标元素指的是触发事件的节点

(1)事件捕获

鼠标点击或者触发了dom事件,浏览器会从根节点(Document 对象)流向目标元素,途中会经过目标元素的各个父级节点,并在这些节点上触发捕获事件,直至到达事件的目标元素

(2)事件冒泡

在捕获完成后,与事件捕获相反,事件会从目标元素流向文档根节点,途中会经过目标元素的各个父级节点,并在这些节点上触发捕获事件,直至到达文档的根节点

2、如何创建事件捕获、事件冒泡

(1)jQuery

addEventListener(type,listener,useCapture)
type:事件类型
listener:事件监听处理函数
useCapture:设置事件查找方式(布尔值,可选)
false,冒泡事件(默认值)
true, 捕获事件
useCapture设置为true后,是在捕获时进行的事件, 默认为false是在冒泡时进行的事件


<div class="outer">outer<div class="center">center<div class="inside">inside</div></div>
</div><script>
const outer = document.querySelector('.outer')
const center = document.querySelector('.center')
const inside = document.querySelector('.inside')outer.addEventListener('click',(e) => {console.log('捕获 outer clicked')},true
)center.addEventListener('click',(e) => {console.log('捕获 center clicked')},true
)inside.addEventListener('click',(e) => {console.log('捕获 inside clicked')},true
)outer.addEventListener('click', (e) => {console.log('冒泡 outer clicked')
})center.addEventListener('center', (e) => {console.log('冒泡 center clicked')
})inside.addEventListener('click', (e) => {console.log('冒泡 inside clicked')
})
</script>

(2)Vue

Vue使用@click绑定事件,默认是事件冒泡,Vue提供了@click.capture来监听事件捕获

<template><div class="outer" @click.capture="clickOuterCapture" @click="clickOuter">outer<div class="center" @click.capture="clickCenterCapture" @click="clickCenter">center<div class="inside" @click.capture="clickInsideCapture" @click="clickInside">inside</div></div></div>
</template><script>
export default {methods: {clickOuterCapture() {console.log('捕获 outer clicked')},clickCenterCapture() {console.log('捕获 center clicked')},clickInsideCapture() {console.log('捕获 inside clicked')},clickOuter() {console.log('冒泡 outer clicked')},clickCenter() {console.log('冒泡 center clicked')},clickInside() {console.log('冒泡 inside clicked')}}
}
</script>

 点击inside执行顺序:

3、如何阻止事件的冒泡

(1)jQuery

event.stopPropagation()和event.stopImmediatePropagation();

如果元素绑定多个事件stopImmediatePropagation会阻止该元素的其他事件,stopPropagation则不会

<div class="outer">outer<div class="center">center<div class="inside">inside</div></div>
</div><script>
const outer = document.querySelector('.outer')
const center = document.querySelector('.center')
const inside = document.querySelector('.inside')outer.addEventListener('click',(e) => {console.log('捕获 outer clicked')},true
)center.addEventListener('click',(e) => {console.log('捕获 center clicked')},true
)inside.addEventListener('click',(e) => {console.log('捕获 inside clicked')},true
)outer.addEventListener('click', (e) => {console.log('冒泡 outer clicked')
})center.addEventListener('center', (e) => {console.log('冒泡 center clicked')
})inside.addEventListener('click', (e) => {e.stopPropagation()console.log('冒泡 inside clicked')
})
</script>

(2)Vue

@click.stop="fun"

<template><div class="outer" @click.capture="clickOuterCapture" @click="clickOuter">outer<div class="center" @click.capture="clickCenterCapture" @click="clickCenter">center<div class="inside" @click.capture="clickInsideCapture" @click.stop="clickInside">inside</div></div></div>
</template><script>
export default {methods: {clickOuterCapture() {console.log('捕获 outer clicked')},clickCenterCapture() {console.log('捕获 center clicked')},clickInsideCapture() {console.log('捕获 inside clicked')},clickOuter() {console.log('冒泡 outer clicked')},clickCenter() {console.log('冒泡 center clicked')},clickInside() {console.log('冒泡 inside clicked')}}
}
</script>

就算是父元素绑定了点击事件处理器,它们也不会被触发

 点击inside执行顺序:

4、元素绑定多个事件时,事件捕获,事件冒泡执行顺序

无论是冒泡事件还是捕获事件,元素都会先执行捕获阶段。

从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素

<div id='one'><div id='two'><div id='three'><div id='four'></div></div></div>
</div><script type='text/javascript'>var one=document.getElementById('one');var two=document.getElementById('two');var three=document.getElementById('three');var four=document.getElementById('four');
</script>

(1)分析一

one.addEventListener('click',function(){alert('one 捕获');
},true);two.addEventListener('click',function(){alert('two 冒泡');
},false);three.addEventListener('click',function(){alert('three 捕获');
},true);four.addEventListener('click',function(){alert('four 冒泡');
},false);

(1)点击four元素,four元素为目标元素,one为根元素祖先,从one开始向下判断执行。

分析:

one为捕获事件,输出one 捕获;
two为冒泡事件,忽略;
three为捕获时间,输出three 捕获;
four为目标元素,开始向上冒泡执行,输出four 冒泡;
three为捕获已执行,忽略;
two为冒泡事件,输出two 冒泡;
one为捕获已执行,忽略。

(2)点击three元素,three元素为目标元素,one为根元素祖先,从one开始向下判断执行。

one为捕获事件,输出one 捕获;
two为冒泡事件,忽略;
three为捕获时间,输出three 捕获,然后开始向上冒泡;
two为冒泡事件,输出two 冒泡;
one为捕获已执行,忽略。

(2)分析二

one.addEventListener('click',function(){alert('one 捕获');
},true);two.addEventListener('click',function(){alert('two 冒泡');
},false);two.addEventListener('click',function(){alert('two 捕获');
},true);three.addEventListener('click',function(){alert('three 冒泡');
},true);four.addEventListener('click',function(){alert('four 捕获');
},true);

(1)点击two元素,two为目标元素;one为根元素祖先,从one开始向下判断执行。

分析:
one为捕获事件,输出one 捕获;
two先执行冒泡事件,two 冒泡;
two再执行捕获事件,two 捕获;
one为捕获已执行,忽略。

(2)点击three元素,three为目标元素;one为根元素祖先,从one开始向下判断执行。

分析:

one为捕获事件,输出one 捕获;
two先执行捕获事件,输出two 捕获;
three为目标元素,开始向上冒泡执行,输出three 冒泡;
two再执行冒泡事件;输出two 冒泡;
one为捕获已执行,忽略。

5、事件委托(事件代理)

事件委托又称事件代理,是 JavaScript 中常用绑定事件的常用技巧。事件委托即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。

事件委托的原理是DOM元素的事件冒泡。

优点

(1)减少内存消耗

使用事件委托可以大量节省内存,减少事件的定义,例如使用事件委托的方式将点击事件绑定到 ul 标签上,就可以实现监听所有 li 标签,简洁、高效。

(2)动态绑定

在网页中,有时我们需要动态增加或移除页面中的元素,使用事件委托不需要再为新增的元素绑定事件,也不需要为删除的元素解绑事件。

5-1、如何创建事件委托

(1)JQuery
<ul><li>item 1</li><li>item 2</li><li>item 3</li><li>item 4</li><li>item 5</li>
</ul><script>
// 事件委托的核心原理:给父节点添加侦听器,利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {// e.target 这个可以得到我们点击的对象for (var i = 0; i < ul.children.length; i++) {ul.children[i].style.backgroundColor = ''}e.target.style.backgroundColor = 'pink'
})
(2)Vue
<template><ul @click.passive="select"><li>item 1</li><li>item 2</li><li>item 3</li><li>item 4</li><li>item 5</li></ul>
</template><script>
export default {methods: {select(event) {// 获取点击的元素if (event.target.tagName === 'li') {// 如果点击的是li,执行相应的操作console.log('li clicked')}}}
}
</script>
注意:当目标元素有子元素时
(1)JQuery

$(selector).on(event, childSelector,data,function);

event:必选;事件的名称(可以自定义) 支持绑定多个事件,多个事件用空格分开,也可以是map参数和数组;
childSelector:可选,添加事件程序的子元素而且不是父选择器本身;
data:可选,传递到事件对象 event的额外的参数;
function:必选;规定事件发生时运行的函数

<div id="parent"><button class="child">按钮1</button><a href="#" class="child">链接1</a><div class="child">其他元素</div>
</div><script>
$(document).ready(function () {$('#parent').on('click', '.child', function (event) {// 检查触发事件的子元素类型if ($(this).is('button')) {console.log('按钮被点击')} else if ($(this).is('a')) {console.log('链接被点击')} else {console.log('其他元素被点击')}})
})// $(this).is('selector')来检查当前点击的子元素是什么类型
</script>
(2)Vue
<template><ul @click.passive="select"><button class="child">按钮1</button><a href="#" class="child">链接1</a><div class="child">其他元素</div></ul>
</template><script>
export default {methods: {select(event) {// 获取点击的元素if (event.target.tagName === 'buttom') {console.log('按钮被点击')} else if (event.target.tagName === 'a') {// 如果点击的是a,执行相应的操作console.log('链接被点击')} else {console.log('其他元素被点击')}}}
}
</script>

5-2、如何取消事件委托

(1)JQuery

使用 event.preventDefault() 方法可以取消事件的默认行为,从而阻止事件委托的触发。通常用于链接的点击、表单的提交等。

(2)Vue

@click.prevent="函数名"

参考文章:一个DOM元素绑定多个事件时,先执行冒泡还是捕获_点击一个元素先捕获-CSDN博客


http://www.ppmy.cn/devtools/37144.html

相关文章

《Python编程从入门到实践》day21

# 昨日知识点回顾 设置背景颜色 在屏幕中央绘制飞船 # 今日知识点学习 12.5 重构&#xff1a;方法_check_events()和_update_screen() 12.5.1 方法_check_events() import sys import pygame from Settings import Settings from Ship import Shipclass AlienInvasion:"…

Docker镜像的创建和Dockerfile

一. Docker 镜像的创建&#xff1a; 1.基于现有镜像创建: &#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改docker run -it --name web3 centos:7 /bin/bash #启动容器​yum install -y epel-release #安装epel源yum install -y nginx #安…

代码随想录day60 | 动态规划P17 | ● 647. ● 516.● 动态规划总结篇

今天 结束动态规划章节 正好是60天 fighting 647. 回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的…

【spark(零)】spark技术概览

文章目录 一. Spark入门二. Spark RDD与 Spark core三. Spark SQL四. Spark Streaming五. Spark内核原理 一. Spark入门 Spark基础知识 Spark部署模式、 Spark运行流程 【概述】spark&#xff08;一&#xff09;:spark特点、知识范畴、spark架构、任务提交流程、支持哪些运行…

JavaScript 中的 Class 类

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f525; 引言&#x1f3af; 基础知识&#x1f3d7;️ 构造函数 (Constructor)&#x1f510; 私有字段 (Private Fields)&#x1f510; 私有方法 (Private Methods)&#x1f9ec; 继承 (Inheritance)&#x1f4e6; 静态…

线性滤波和预测理论的新成果【1961.Kalman】翻译

线性滤波和预测理论的新成果 New Results in Linear Filtering and Prediction TheoryR. 线性滤波与预测理论的新结果[j]。 E. KALMAN Study, Baltimore, MarylandResearch Institute for AdvancedR. E.卡尔曼研究&#xff0c;巴尔的摩&#xff0c;马里兰州高级研究所。 S. …

从简单逻辑到复杂计算:感知机的进化与其在现代深度学习和人工智能中的应用(下)

文章目录 第一章&#xff1a;感知机的局限性1.1 异或门的挑战1.2 线性与非线性问题 第二章&#xff1a;多层感知机2.1 已有门电路的组合2.2 实现异或门 第三章&#xff1a;从与非门到计算机 文章文上下两节 从简单逻辑到复杂计算&#xff1a;感知机的进化与其在现代深度学习和人…

Kafka应用Demo:按主题订阅消费消息

安装环境 Kafka安装可参考官方网站的指导(https://kafka.apache.org/quickstart), 按步骤解压压缩包&#xff0c;修改配置。然后再启动zookeeper和kafka-server即可。 需要注意的一点&#xff1a;如果是在VMware虚拟机上启动的kafka, 需要修改一下server.properties配置文件&am…