当前位置: 首页 > news >正文

事件捕获vs 事件冒泡,延申事件委托

事件捕获vs事件冒泡

  • 拿点击事件举例子,点击dom树的某个目标节点:
    • 事件捕获:从根节点到目标节点扩散
    • 事件冒泡:从目标节点到根节点扩散
  • 扩散就是说,途中的节点,相应的点击事件都会被触发
    但是,只能,拦截其中一个方向,也就是,要么,在捕获阶段拦截,要么在冒泡阶段拦截。
    target.addEventListener(eventType,hander,useCapture);第三个参数,useCapture,是否在捕获阶段触发。true就是在捕获阶段触发,false就是在冒泡极端触发
<body><div class="parent"><div class="child1">child1<div class="grandson1">grandson1</div></div><div class="child2">child2</div></div>
</body>
<script>let child1=document.getElementsByClassName('child1')[0];let grandson1=document.getElementsByClassName('grandson1')[0];child1.addEventListener('click',function(event){console.log(this,event.target)})grandson1.addEventListener('click',function(event){console.log('grandson1',event,this)})
</script>

只简单分析dom对象
在这里插入图片描述
假设点击,grandson1,捕获阶段,就是从parent->child1->grandson1;冒泡阶段,就是grandson1->child1->parent
这三个节点,要么,你在捕获阶段监听,

    child1.addEventListener('click',function(event){console.log(this,event.target)}true)

要么在,冒泡阶段监听

    child1.addEventListener('click',function(event){console.log(this,event.target)})

事件委托

其实就是把某个元素的事件,委托给祖先元素。
在这里插入图片描述
就比如,child1下面有很多节点,如果对每个节点都监听click事件的化,会造成资源浪费,代码也冗余,所以一般可以,在冒泡阶段拦截,用event.target获取点击的元素。

    let child1=document.getElementsByClassName('child1')[0];let grandson1=document.getElementsByClassName('grandson1')[0];child1.addEventListener('click',function(event){let t=event.targetif(t===this){console.log('clicked child1,noting to do');return;}// 有可能grandson里面还有元素,业务上一般需要,获取grandson这一层while(t&&t!==this){if(t.parentNode===this){break}t=t.parentNode;}// do something...console.log(t.innerText,'triggered')});
  • 为什么要对t===this做判断?用户可能点击的是代理层,也就是child1;
  • 为什么要while,因为有可能grandsonN中有其他子元素,但一般我们需要获取的是grandsonN这一层的信息,所以需要循环到gransonN这一层
  • 为什么要用t=event.target,你是改不了event.target滴~

stopPropagation vs preventDefault

区别
stopPropagation阻止冒泡事件
preventDefault阻止默认事件。e.g. 点击a标签会跳转到href,点击form buttom会提交表单

    <div class="parent"><div class="child1">child1<div class="grandson1">grandson1</div></div><div class="child2">child2</div></div>
    let child1=document.getElementsByClassName('child1')[0];let grandson1=document.getElementsByClassName('grandson1')[0];let parent=document.getElementsByClassName('parent')[0];child1.addEventListener('click',function(event){let t=event.targetif(t===this){console.log('clicked child1,noting to do');return;}// 有可能grandson里面还有元素,业务上一般需要,获取grandson这一层while(t&&t!==this){if(t.parentNode===this){break}t=t.parentNode;}// do something...console.log(t.innerText,'triggered');console.log("current target",event.currentTarget);event.stopPropagation(); //  preventDefault是拦截不住的,因为冒泡不是默认事件console.log("stopped propagations") // 停止冒泡,不会往上传到parent了});parent.addEventListener('click',function(event){console.log("on parent click")})

pointer-event

css有一个属性是pointer-events 控制鼠标事件
某个元素设置成pointer-events:none,那么元素不会响应鼠标事件,显然,在上面例子中,如果我把 grandson1的样式设置成这个,点击grandson1 不会输出on grandson1 click但是,会输出on child1 click,on parent click,也就是只是当前元素,不会相应鼠标事件而已(click,mouseover…),但是事件还是会扩散。如果设置为auto,那就相当于没有设置pointer-events这个属性,正常触发。

    <div class="parent"><div class="child1">child1<div class="grandson1 disabled">grandson1</div></div><div class="child2">child2</div></div>
    .disabled{pointer-events: auto;/* cursor只是改变了样式,还是会触发事件的 *//* cursor:not-allowed;  */}
    let child1=document.getElementsByClassName('child1')[0];let grandson1=document.getElementsByClassName('grandson1')[0];let parent=document.getElementsByClassName('parent')[0];grandson1.addEventListener('click',function(event){console.log('on grandson1 click') });child1.addEventListener('click',function(event){console.log('on child1 click')});parent.addEventListener('click',function(event){console.log("on parent click")})

输出:
在这里插入图片描述

http://www.lryc.cn/news/477385.html

相关文章:

  • 接口测试(十一)jmeter——断言
  • 使用buildx构建多架构平台镜像
  • 宠物领养救助管理软件有哪些功能 佳易王宠物领养救助管理系统使用操作教程
  • Spring Boot中实现多数据源连接和切换的方案
  • 科技资讯|谷歌Play应用商店有望支持 XR 头显,AR / VR设备有望得到发展
  • 关于read/write 网络IO、硬盘IO的区别
  • vue2开发 对接后端(go语言)常抛异常情况以及处理方法汇总
  • LSTM:解决梯度消失与长期依赖问题
  • Kafka在大数据处理中的作用及其工作原理
  • w~自动驾驶~合集5
  • Java优先队列的使用
  • 20241105,LeetCode 每日一题,用 Go 实现两数之和的非暴力解法
  • mysql之命令行基础指令
  • 使用Django Channels实现WebSocket实时通信
  • 「Mac畅玩鸿蒙与硬件27」UI互动应用篇4 - 猫与灯的互动应用
  • Spring-Day4
  • C#-类:成员属性
  • qt QDragEnterEvent详解
  • Vue项目与IE浏览器的兼容性分析(Vue|ElementUI)
  • 【C++之STL】一文学会使用 string
  • 好用的办公套件--- ONLYOFFICE
  • Android View事件分发
  • 攻防世界GFSJ1229 Three
  • 2023 icpc杭州(M,J,D,G,H)
  • 在CentOS 7上安装Alist
  • 【C/C++】memcpy函数的模拟实现
  • 嵌入式开发之线程互斥
  • JavaScript 变量作用域与函数调用机制:var 示例详解
  • Linux(CentOS)安装 JDK
  • AI产品经理实战手册:策略、开发与商业化指南