欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 前端技术 > javascript >内容正文

javascript

javascript事件的捕获阶段(capture phase) -凯发k8官方网

发布时间:2024/10/12 javascript 29 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 javascript事件的捕获阶段(capture phase) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

最近项目中遇到一个实际问题,自己搞了半天没解决,最后在stackoverflow上求助,不到3分钟就得到了凯发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 和 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

总结

以上是凯发k8官方网为你收集整理的javascript事件的捕获阶段(capture phase)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图