无法理解addEventListener中的useCapture参数

2020/10/07 08:41 · javascript ·  · 0评论

我已阅读https://developer.mozilla.org/en/DOM/element.addEventListener上的文章,但无法理解useCapture属性。定义有:

如果为true,useCapture指示用户希望启动捕获。启动捕获后,所有指定类型的事件都将分派给已注册的侦听器,然后才分派给DOM树中其下的任何EventTarget。在树中冒泡的事件不会触发指定使用捕获的侦听器。

在此代码中,parent事件在child之前触发,因此我无法理解其行为。Document对象的usecapture为true,child div的usecapture设置为false,并且遵循了useuseture的文档。因此为什么document属性比child优先。

function load() {
  document.addEventListener("click", function() {
    alert("parent event");
  }, true);

  document.getElementById("div1").addEventListener("click", function() {
    alert("child event");
  }, false);
}
<body onload="load()">
  <div id="div1">click me</div>
</body>

可以在两种情况下激活事件:在开始(“捕获”)和结束(“冒泡”)。事件按照其定义的顺序执行。假设您定义了4个事件监听器:

window.addEventListener("click", function(){console.log(1)}, false);
window.addEventListener("click", function(){console.log(2)}, true);
window.addEventListener("click", function(){console.log(3)}, false);
window.addEventListener("click", function(){console.log(4)}, true);

日志消息将按以下顺序显示:

  • 2(首先使用定义capture=true
  • 4(使用定义秒capture=true
  • 1(带有的第一个定义的事件capture=false
  • 3(带有的第二个已定义事件capture=false

我发现此图对于理解捕获/目标/气泡阶段非常有用:http :
//www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

下面是从链接中提取的内容。

相数

该事件是在从树的根到此目标节点的路径后分派的。然后可以在目标节点级别本地处理它,也可以从树中更高级别的任何目标祖先那里处理它。事件分派(也称为事件传播)分为三个阶段,并按以下顺序进行:

  1. 捕获阶段:事件从树的根到目标节点的直接父节点分派给目标的祖先。
  2. 目标阶段:将事件调度到目标节点。
  3. 冒泡阶段:将事件从目标节点的直接父节点分发到目标树的根节点,再分发给目标祖先。

使用DOM事件流在DOM树中调度的事件的图形表示

在事件的初始派发之前确定目标的祖先。如果在分发过程中删除了目标节点,或者添加或删除了目标祖先,则事件传播将始终基于目标节点和在分发之前确定的目标祖先。

某些事件可能不一定完成DOM事件流的三个阶段,例如,只能为一个或两个阶段定义事件。例如,本规范中定义的事件将始终完成捕获阶段和目标阶段,但某些事件将不会完成冒泡阶段(“冒泡事件”与“非冒泡事件”,另请参阅Event.bubbles属性)。

捕获事件(useCapture = true)与泡泡事件(useCapture = false

MDN参考

  • 捕获事件将在冒泡事件之前调度
  • 事件传播顺序为

    1. 家长捕获
    2. 儿童捕捉
    3. 目标捕获和目标泡泡

      • 按照注册顺序
      • 当元素是事件的目标时,useCapture参数无关紧要(感谢@bam和@ legend80s)
    4. 儿童泡泡
    5. 父母泡泡
  • stopPropagation() 将停止流动

使用捕获流

演示版

结果:

  1. 家长捕获
  2. 目标泡泡1

    (因为Capture和Target的Bubble将按照注册顺序触发,因此Bubble事件在Capture事件之前触发)

  3. 目标捕获

  4. 目标泡泡2
  5. 父母泡泡
var parent = document.getElementById('parent'),
target = document.getElementById('target');

target.addEventListener('click', function (e) { 
console.log('Target Bubble 1');
// e.stopPropagation();
}, false);

target.addEventListener('click', function (e) { 
console.log('Target Capture');
// e.stopPropagation();
}, true);

target.addEventListener('click', function (e) { 
console.log('Target Bubble 2');
// e.stopPropagation();
}, false);

parent.addEventListener('click', function (e) { 
console.log('Parent Capture');
// e.stopPropagation();
}, true);

parent.addEventListener('click', function (e) { 
console.log('Parent Bubble');
// e.stopPropagation();
}, false);
<div id="parent">
    <button id="target" style="padding: 1em 0.8em;">
        Trigger event
    </button>
</div>

当您说useCapture = true时,事件在捕获阶段从上至下执行,为false时,它会从上到下执行气泡。

全部与事件模型有关:http : //www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow
您可以在冒泡阶段或捕获阶段捕获事件。
你的选择。


看看
http://www.quirksmode.org/js/events_order.html-您会发现它非常有用。

代码示例:

<div id="div1" style="background:#9595FF">
  Outer Div<br />
  <div id="div2" style="background:#FFFFFF">
    Inner Div
  </div>
</div>

JavaScript代码:

d1 = document.getElementById("div1");
d2 = document.getElementById("div2");

如果两者都设置为false

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);

执行:单击内部Div时,警报显示为:Div 2> Div 1

这里的脚本是从内部元素执行的:事件冒泡(useCapture已设置为false)

div 1设置为true且div 2设置为false

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);

执行:单击内部Div时,警报显示为:Div 1> Div 2

这里的脚本是从祖先/外部元素执行的:事件捕获(useCapture已设置为true)

div 1设置为false且div 2设置为true

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);

执行:单击内部Div时,警报显示为:Div 2> Div 1

这里的脚本是从内部元素执行的:事件冒泡(useCapture已设置为false)

div 1设置为true且div 2设置为true

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);

执行:单击内部Div时,警报显示为:Div 1> Div 2

此处,脚本是从祖先/外部元素执行的:由于useCapture设置为true,因此进行事件捕获

概要:

DOM规范中描述:

https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

工作方式如下:

在从document的根()到目标节点的路径后调度事件目标节点是最深的HTML元素,即event.target。事件分派(也称为事件传播)分为三个阶段,并按以下顺序进行:

  1. 捕获阶段:事件从树的根(document分发到目标节点的直接父节点,分发给目标的祖先
  2. 目标阶段:将事件调度到目标节点。目标阶段始终位于html事件被分配的最深层元素上。
  3. 冒泡阶段:将事件从目标节点的直接父节点分发到目标树的根节点,再分发给目标祖先。

事件冒泡,事件捕获,事件目标

例:

// bubbling handlers, third argument (useCapture) false (default)
document.getElementById('outerBubble').addEventListener('click', () => {
  console.log('outerBubble');
}, false)

document.getElementById('innerBubble').addEventListener('click', () => {
  console.log('innerBubble');
}, false)


// capturing handlers, third argument (useCapture)  true
document.getElementById('outerCapture').addEventListener('click', () => {
  console.log('outerCapture');
}, true)

document.getElementById('innerCapture').addEventListener('click', () => {
  console.log('innerCapture');
}, true)
div:hover{
  color: red;
  cursor: pointer;
}
<!-- event bubbling -->
<div id="outerBubble">
  <div id="innerBubble">click me to see Bubbling</div>
</div>


<!-- event capturing -->
<div id="outerCapture">
  <div id="innerCapture">click me to see Capturing</div>
</div>

上面的示例确实说明了事件冒泡和事件捕获之间的区别。使用添加事件侦听器时addEventListener,还有第三个元素称为useCapture。将此boolean设置为时,true允许事件侦听器使用事件捕获而不是事件冒泡。

在我们的示例中,当我们将useCapture参数设置为时,false我们看到事件冒泡发生了。首先触发目标阶段的事件(记录innerBubble),然后通过事件冒泡触发父元素中的事件(记录externalBubble)。

当我们将useCapture参数设置为时,true我们会看到外部事件<div>首先被触发。这是因为事件现在在捕获阶段而不是冒泡阶段中触发。

考虑到活动旅行的三个阶段

  1. 捕获阶段:事件被分派到目标的祖先从树的根部到目标节点的直接父。
  2. 目标阶段:事件被分派到目标节点。
  3. 冒泡阶段:事件从目标节点到树的根的直接父派遣到目标的祖先。

useCapture指示事件旅行将在哪个阶段进行:

如果为true,则useCapture指示用户仅希望为捕获阶段添加事件侦听器,即,在目标和冒泡阶段不会触发该事件侦听器。如果为false,则事件监听器仅在目标和冒泡阶段被触发

来源与第二个最佳答案相同:https : //www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

仅当项目处于相同级别时,定义顺序才重要。如果您颠倒了代码中的定义顺序,您将获得相同的结果。

但是,如果您反转两个事件处理程序上的useCapture设置,则子事件处理程序将在父事件处理程序之前响应。这样做的原因是,现在将在捕获阶段之前触发子事件处理程序,而捕获阶段将在触发父事件处理程序的冒泡阶段之前进行。

如果将两个事件处理程序的useCapture都设置为true(无论定义顺序如何),则将首先触发父事件处理程序,因为它在捕获阶段位于子项之前。

相反,如果将两个事件处理程序的useCapture都设置为false(同样与定义顺序无关),则子事件处理程序将首先被触发,因为它在冒泡阶段位于父项之前。

本文地址:http://javascript.askforanswer.com/wufalijieaddeventlistenerzhongdeusecapturecanshu.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!