JS 事件冒泡防止复选框选中状态

Posted

技术标签:

【中文标题】JS 事件冒泡防止复选框选中状态【英文标题】:JS event bubbling prevents checkbox checked status 【发布时间】:2019-09-17 18:40:56 【问题描述】:

我尝试了解事件冒泡和事件隧道(在 javascript 中捕获)之间的区别。

在 wpf 中,您必须在事件到达控件之前处理该事件。在 js 中似乎并非如此。

为什么捕获真假没有区别?我预计,在底部的示例中选中了该复选框。我不想阻止事件传播,只是了解这种影响。

document.querySelector("html").addEventListener("click", function(event) 
  document.getElementById("output-box").innerHTML += "Sorry! <code>preventDefault()</code> won't let you check this!<br>";
  event.preventDefault();
, 
  capture: false
);
<p>Please click on the checkbox control.</p>

<form>
  <label for="id-checkbox">Checkbox:</label>
  <input type="checkbox" id="id-checkbox" />
</form>

<div id="output-box"></div>

【问题讨论】:

【参考方案1】:

引用 MDN useCapture 选项只会影响事件沿 DOM 树向下传播的顺序。

一个布尔值,指示此类型的事件在被分派到 DOM 树中它下面的任何 EventTarget 之前是否会被分派到已注册的侦听器。

只要您的 sn-p 只有一个事件侦听器,您确实不会注意到任何可观察到的效果。 但是,如果您添加另一个,即

document.querySelector("#id-checkbox").addEventListener("click", function(event) 
    document.getElementById("output-box").innerHTML += "Checkbox capture";       
);

您会注意到执行顺序如何根据外部处理程序捕获选项而变化。 如果你想选中复选框,你可以像这样使用它。

document.querySelector("#id-checkbox").addEventListener("click", function(event) 
    event.stopPropagation();    
    document.getElementById("output-box").innerHTML += "Checkbox capture";       
);

这里stopPropagation 防止事件冒泡。所以事件不会在 DOM 树中被处理,preventDefault 也不会被调用。 如果您只想执行上层处理程序,您可以使用

document.querySelector("html").addEventListener("click", function(event) 
  document.getElementById("output-box").innerHTML += "Sorry! <code>preventDefault()</code> won't let you check this!<br>";
  event.stopPropagation();
  event.preventDefault();
, 
  capture: true
);

这里capture: truestopPropagation 的组合可以防止在DOM 树中捕获事件。

【讨论】:

但是它并不能像这张图片所解释的那样工作:w3.org/TR/DOM-Level-3-Events/images/eventflow.svg 我会争辩说,你需要捕获阶段来阻止控件的事件处理,但情况似乎并非如此. 这张图片告诉我们的是捕获阶段的执行是为了确定事件目标。如果您检查处理程序的event.target,它将显示 HTMLInput 元素,尽管您处理“html”标记单击而不是您的复选框。第二个冒泡阶段旨在执行所有订阅者。因此,如果您像我的示例中那样有 2 个订阅者,则两者都将被执行。但是,如果您想避免这种情况,您可以在复选框处理程序中添加 event.stopPropagation();。这将使您的复选框被选中 如果我有捕获 true/false 的 stopPropagation,那么我总是可以选中该复选框。但是事件被丢弃不是吗? 我不确定您所说的“丢弃”是什么意思。我的观点是 stopPropagation 可以防止进一步冒泡。这就是为什么如果你在复选框级别的某个地方处理它,它不会到达触发 preventDefault 的 html 级别处理程序。 如果我用 capture = true stopPropagation 仍然可以选中复选框。【参考方案2】:

正如文档所解释的,这个 var 是一个布尔值,指示在传递给下一个元素的事件侦听器之前是否应该将事件传递给当前事件处理程序。 只需明白,当您在 js 中触发事件时,它首先会传递给“第一个”元素,并且会越来越深。然后,当它到达最深的元素时,事件会回到第一个元素(我们说的是冒泡)。

这个例子应该可以帮助你理解:

document.getElementsByTagName("input")[0].addEventListener("click", function(event) 
  alert("event from the checkbox");
);

document.getElementsByTagName("body")[0].addEventListener("click", function(event) 
  alert("event from the body");
, 
  capture: false
);
<p>Please click on the checkbox control.</p>

<form>
  <label for="id-checkbox">Checkbox:</label>
  <input type="checkbox" id="id-checkbox" />
</form>

<div id="output-box"></div>

【讨论】:

以上是关于JS 事件冒泡防止复选框选中状态的主要内容,如果未能解决你的问题,请参考以下文章

JS事件——禁止事件冒泡和禁止默认事件

jquery如何阻止事件冒泡

jquery中如何防止冒泡事件

Javascript事件冒泡,没有想象中那么糟糕

关于JS 事件冒泡和onclick,click,on()事件触发顺序

jquery的mouseover方法如何阻止事件冒泡