JavaScript事件的捕获阶段(Capture phase)
最近项目中遇到一个实际问题,自己搞了半天没解决,最后在StackOverflow上求助,不到3分钟就得到了解决方案,而且答案意外的很简单——加一个参数。
场景是这样的:有一个表格(事实上这样的表格在这个系统很多),每一行(row)是顾客的信息(名字,订单号,付款金额...),要求点击表格行(tr元素)打开订单详情,点击顾客名字(包裹在一个a元素里,a在td里)时打开顾客信息页面,不打开订单详情。这不简单直接么,jQuery把a元素和tr元素的事件都委托给tbody或者table不就可以了么?
$('tbody').on('click', 'tr', function() {alert('order detail...')}).on('click', 'a', function(e) {e.stopPropagation()alert('contact detail')})
如果只是在当前单个页面的代码里写这段,没问题。但因为项目很多页面都有这样包含"<a>顾客名字</a>"的地方,于是我干脆在一个每个页面都会引用的js文件中加了一段把这样的a元素(元素类名取为“gotocontact”)的handler委托给document元素的代码,如下(这里假设a元素是叶子元素,即不会有子元素):
// 因为此时还没引入jQuery,所以用了原生方法 document.addEventListener('click', function(e) {var el = e.srcElement || e.target;if (el && el.classList && el.classList.contains('gotocontact')) {e.stopPropagation();alert('going to contact...')} })
然后在那个页面的代码里把tr元素的handler委托给tbody(id为“list”):
$('#list').on('click', 'tr', function() {alert('order detail...')})
结果这样是有问题的,当点击a元素时两个handler都会触发,不符合预期。
stackoverflow上的答案是在addEventListener参数里添加第三个参数:
document.addEventListener('click', function(e) {var el = e.srcElement || e.target;if (el && el.classList && el.classList.contains('gotocontact')) {e.stopPropagation();alert('going to contact...')} }, true) // ^^^^ add third parameter
问题解决。一个参数就解决了?!
知道addEventListener有这个参数选项(MDN),但是根本不知道起什么作用。
然后开始搜索,看到了这篇文章,算是讲得比较通俗易懂的:
W3C标准中DOM事件有3个阶段:capture phase(捕获阶段), target phase(目标阶段), bubble phase(冒泡阶段)。而常用的on<event> 和 addEventListener(event, handler) (注意没有第三个参数)只会作用于后两个阶段。如下图(来自W3C):
把W3C对这张图的说明简单翻译下搬过来:
事件生成后,事件的传播路径(propagation path)先被确定下来,路径是一个有序列表,列表中最后一个元素是目标元素,往前依次是目标元素的父元素、祖先元素,一直到Window对象。接下来事件开始传播(propagate):
1.捕获阶段。事件对象从Window对象开始沿传播路径向下,依次经过各元素传播至目标元素的父元素;
2.目标阶段。事件对象到达目标元素;
3.冒泡阶段。事件对象从目标元素的父元素开始沿传播路径向上,依次经过各元素传播至Window对象。
照着图拿本例来看。没加第三个参数时,两个handler都只在冒泡阶段起作用(jQuery的on方法就是addEventListener不加第三个参数的包装)。当我点击a.gotocontact时,事件对象从Window到达a标签元素这段时间内都没有触发handler。事件对象到达tbody#list时,触发其handler,alert('order detail...'),而此处没有stopPropagation(也不能有,否则事件传播不到document,document的handler就不会触发)。之后到达document,触发handler,alert('going to contact'),而此处的stopPropagation也只是不让事件传到最后的Window对象,事件基本走完了传播路径的一个往返。
加上第三个参数时,addEventListener添加的handler会在捕获阶段起作用。事件传播到document元素时触发handler,这里的stopPropagation停止事件进一步传播。事件刚走了一步就被停止传播,到不了tbody#list,达到预期效果。
参考:
1. Bubbling and capturing
2. UI Events
3. Event | MDN
转载于:https://www.cnblogs.com/Monkey-D-Pixel/p/10070331.html
JavaScript事件的捕获阶段(Capture phase)相关推荐
- 深入浅出 Javascript 事件
转载自:https://www.cnblogs.com/jingwhale/p/4656869.html 深入浅出 Javascript 事件 一.事件流 事件冒泡和事件捕获分别由微软和网景公司提出, ...
- javaScript事件(一)事件流
一.事件 事件是文档或者浏览器窗口中发生的,特定的交互瞬间. 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字. 事件是javaScript和DOM之间交 ...
- JavaScript 事件相关
一.如何理解JavaScript事件? 个人理解是浏览器或鼠标或键盘触发某个行为而产生的交互.它可能是某种鼠标行为(点击.按下.划过....),也可能是某种键盘操作,亦或是浏览器发生的行为(文档加载完 ...
- JavaScript事件流
JS事件流 1. 什么是事件流 ? 2. 事件流模型 2.1) 事件冒泡 2.2) 事件捕获 3. DOM 事件流 1. 什么是事件流 ? 在学习事件流之前我们先看看什么是事件 ? 事件代表文档或浏览 ...
- javascript事件代理
一,事件介绍 1.事件用来实现js和html之间交互,网页中的每个元素都有一些事件属性可以触发事件处理函数. 2.一个完整的事件包含 (1)事件源 (html元素) (2)事件类型 (click,mo ...
- 谈谈JavaScript事件
何为'事件' 用户在网页中的行为叫做事件 学习事件的目的:希望能自定义的让用户在网页中进行某种行为之后,去执行写好一段代码 语法: 1.事件源.on事件类型=function() {} 2.行内绑定: ...
- JavaScript(事件)
事件定义 用户在网页中的行为叫做事件 学习事件的目的:希望能自定义的让用户在网页中进行某种行为之后,去执行写好一段代码 语法: 事件源:on事件类型 = 函数 行内绑定:<标签 on 事件类型 ...
- addeventlistener事件第三个参数_简析JavaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序...
这篇文章主要介绍了javaScript 事件绑定.事件冒泡.事件捕获和事件执行顺序整理总结的相关资料 (一)事件绑定的几种方式 javascript给DOM绑定事件处理函数总的来说有2种方式:在htm ...
- 简析JavaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序
JavaScript 事件绑定.事件冒泡.事件捕获和事件执行顺序 这篇文章主要介绍了javaScript 事件绑定.事件冒泡.事件捕获和事件执行顺序整理总结的相关资料 (一)事件绑定的几种方式 jav ...
最新文章
- gevent queue应用2 队列设置了最大数量限制
- ios10申请权限以及弹出允许使用数据框
- React 中 keys 的作用是什么?
- 教徒计划出品:升级ESXI41-ESXI5
- 本地windows主机无法访问虚拟机里主机解决办法
- 路由与交换技术(铺垫内容)
- Intel CPU 曝两个新漏洞影响所有处理器,设备可遭接管(含视频)
- Ubuntu安装最新版nodejs
- 微信短视频小程序——视频封面,视频缩略图
- 1386 - Cellular Automaton
- 关于ROHDESCHWARZ公司电流探头EZ-17系数修正的说明
- 什么是firmware?
- 依赖、关联、聚合、组合
- Linux进程(上)
- python字符串算式加减运算(Python字符串运算)
- js moment.js 给定时间 获取自然月、周的时间轴
- 抛物线断面临界水深莫洛图
- AWS上配置Cisco ASAv AnyConnect
- 时钟偏差、延迟、不确定度、抖动 (skew,latency,uncertainty,jitter)
- 如何用 Lightly 进行 Debug 断点调试?
热门文章
- HDFS restful API:关于WebHDFS与HttpFS的区别
- 【网址收藏】WSL安装docker(不折腾版)
- 【收藏】keepalived nginx服务检测脚本
- win10安装docker desktop之后没有ADVANCED选项解决办法
- 解决kubesphere node-exporter守护进程pod安装失败的问题
- vSphere资源:下载及文档地址
- Hadoop hdfs 从指定偏移量读取文件数据代码示例
- Python Django 使用cookie实现三天免登录及记住密码功能代码示例
- socket编程的三种通信模型,BIO,NIO,AIO
- vooc是什么快充协议_5G时代除了网速,快充同样重要!