javascript
javascript事件的捕获阶段(capture phase) -ag凯发k8国际
最近项目中遇到一个实际问题,自己搞了半天没解决,最后在stackoverflow上求助,不到3分钟就得到了ag凯发k8国际的解决方案,而且答案意外的很简单——加一个参数。
场景是这样的:有一个表格(事实上这样的表格在这个系统很多),每一行(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')})如果只是在当前单个页面的代码里写这段,没问题。但因为项目很多页面都有这样包含""的地方,于是我干脆在一个每个页面都会引用的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
把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
总结
以上是ag凯发k8国际为你收集整理的javascript事件的捕获阶段(capture phase)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: