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

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.mfbz.cn/a/582350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

百面算法工程师 | 池化相关总结

目录 14.1 什么是池化 14.2 池化层的作用 14.3 平均池化 14.4 最大池化 14.5 空间金字塔池化 14.6 ROI Pooling 14.7 最大池化与平均池化是如何进行反向传播的 14.8 卷积层与池化层的区别 欢迎大家订阅我的专栏一起学习共同进步 祝大家早日拿到offer&#xff01; lets…

位运算、状态压缩、枚举子集汇总

本文涉及知识点 证明容斥原理和证明集合枚举都用到了&#xff1a;二项式定理 【数学归纳法 组合数学】容斥原理 基础知识 位运算优先级 位运算的结合性都是从左到右。优先级低的先运算。 优先级位运算符说明7<< >>位左移/位右移10&按位与11^按位异或12按位…

织梦云端:网络信号原理的艺术解码

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的Linux高性能服务器编程系列之《织梦云端&#xff1a;网络信号原理的艺术解码》&#xff0c;在这篇文章中&#xff0c;你将会学习到网络信号原理以及应用&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图…

【树莓派】yolov5 Lite,目标检测,行人检测入侵报警,摄像头绑定

延续之前的程序&#xff1a; https://qq742971636.blog.csdn.net/article/details/138172400 文章目录 播放声音pygame不出声音怎么办&#xff08;调节音量&#xff09;树莓派上的音乐播放器&#xff08;可选&#xff09;命令行直接放歌&#xff08;尝试放mp3歌曲&#xff09; …

数据结构-二叉搜索树(BST)

目录 什么是二叉搜索树 二叉搜索树的特性 (1)顺序性 (2)局限性 二叉搜索树的应用 二叉搜索树的操作 (1)查找节点 (2)插入节点 (3)删除节点 (4)中序遍历 什么是二叉搜索树 如图所示&#xff0c;二叉搜索树&#xff08;binary search tree&#xff09;满足以下条件。…

【Vivado那些事儿】使用 Python 提取 ILA 数据

ILA应该是调试AMD-Xilinx FPGA最常用的IP。 在调试中&#xff0c;我们希望 ILA 中的波形可以提供有关设计问题的所有信息&#xff0c;但情况并非如此。对于复杂的调试&#xff0c;我们还需要将 ILA 捕获的真实数据存储到可以进一步处理的文件中。根据放置 ILA 的位置&#xff0…

C语言阶段的题目解析

前言 我们C语言已经学习的差不多了&#xff0c;但是C语言之中存在的一些问题与难点我们还不一定能够又快又好地解决&#xff0c;为了夯实我们的基础&#xff0c;我们来练习几道稍微有点难度的C语言习题吧 例题一 题目 int main(void) {unsigned char i 7;int j 0;for (; i…

【PyTorch 实战3:YOLOv5检测模型】10min揭秘 YOLOv5 检测网络架构、工作原理以及pytorch代码实现(附代码实现!)

YOLOv5简介 YOLOv5&#xff08;You Only Look Once, Version 5&#xff09;是一种先进的目标检测模型&#xff0c;是YOLO系列的最新版本&#xff0c;由Ultralytics公司开发。该模型利用深度学习技术&#xff0c;能够在图像或视频中实时准确地检测出多个对象的位置及其类别&…

千锤百炼之每日算法(三)

题外话 不会再水了,先把算法任务完成! 正题 第一题 简写单词 规定一种对于复合词的简写方式为只保留每个组成单词的首字母,并将首字母大写后再连接在一起 比如“College English Test"可以简写成“CET",“Computer Science 可以简写为"CS"&#xff0c;I a…

【深度学习】【Lora训练1】StabelDiffusion,Lora训练过程,秋叶包,Linux,SDXL Lora训练

文章目录 一、环境搭建指南二、个性化安装流程三、启动应用四、打开web五、开始训练 19.27服务器 一、环境搭建指南 打造一个高效且友好的开发环境&#xff1a; 项目源码获取&#xff1a; 通过以下命令轻松克隆项目及所有子模块至您的Linux系统&#xff1a; git clone --recu…

《ElementUI 基础知识》el-tabs header 监听鼠标中键滚动时左右滑动(ElementPlus同样适用)

前言 收到需求&#xff0c;可监听 el-tabs 头在鼠标 hover 时。滑动鼠标中键&#xff0c;可左右滑动&#xff01; 效果 鼠标中键上下滑动时&#xff1b;向上滑&#xff0c;向左移动&#xff1b;向下滑&#xff0c;向右移动&#xff1b; 实现 代码56 - 60行&#xff0c;添加…

寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)

贵工程寝室快修目录 目录 基于SprinBootvue的贵工程寝室快修小程序 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 在线报修管理 3公告信息管理 4论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&a…

操作系统安全:安全审计,Windows系统日志详解,Windows事件ID汇总

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

C++深度解析教程笔记2

C深度解析教程笔记2 第3课 - 进化后的 const 分析实验-C与C的const区别实验-C与C的const区别&const作用域 第4课 - 布尔类型和引用小结 本文学习自狄泰软件学院 唐佐林老师的 C深度解析教程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 第3课 - 进化后…

Unity 递归实现数字不重复的排列组合

实现 private void Permutation(List<int> num, int leftIndex, List<string> strs) {if (leftIndex < num.Count){for (int rightIndex leftIndex; rightIndex < num.Count; rightIndex){Swap(num, leftIndex, rightIndex);Permutation(num, leftIndex 1…

HarmonyOS 鸿蒙下载三方依赖 ohpm环境搭建

前言 ohpm&#xff08;One Hundred Percent Mermaid &#xff09;是一个集成了Mermaid的命令工具&#xff0c;可以用于生成关系图、序列图、等各种图表。我们可以使用ohpm来生成漂亮且可读性强的图表。 本期教大家如何搭建ophm环境&#xff1a; 一、在DevEco Studio中&#…

前端可以掌握的nginx相关操作

一、前言&#xff1a; 在日常开发中&#xff0c;前端工程师可以把打好的前端包直接放到测试服务器上&#xff0c;自己再验证功能是否改好&#xff0c;这样可以提高开发效率&#xff0c;写篇笔记记录一下我个人用到的命令 二、使用的工具 用MobaXterm完成相关操作&#xff0c…

Vue3 + TS 项目实战 - 后台管理系统 - 按钮权限

前期回顾 网站的打赏 —— 新一代的思路-CSDN博客https://blog.csdn.net/m0_57904695/article/details/136704914?spm1001.2014.3001.5501 目录 &#x1f6a9; XX银行_系统管理_按钮权限控制_前端_提测单 项目信息 提测版本信息 功能列表 测试范围 测试环境 ✅ 步…

[paper note]代码生成评估模型-CodeBLEU原理分析

论文信息 论文标题&#xff1a;CodeBLEU: a Method for Automatic Evaluation of Code Synthesis 发表时间&#xff1a;2020年9月 论文原文&#xff1a;CodeBLEU: a Method for Automatic Evaluation of Code Synthesis 论文内容 摘要 评价指标对一个领域的发展起着至关重…

大厂常见算法50题-替换空格

专栏持续更新50道算法题&#xff0c;都是大厂高频算法题&#xff0c;建议关注, 一起巧‘背’算法! 文章目录 题目解法一 String类replace方法解法二 遍历替换总结 题目 解法一 String类replace方法 String类自带的replace&#xff0c;方法传入两个char类型的参数&#xff0c;分…