【问题标题】:stopPropagation/preventDefault behavior on an element inside a link链接内元素的 stopPropagation/preventDefault 行为
【发布时间】:2017-02-21 22:29:36
【问题描述】:

我试图了解<a> 中的元素具有event.stopPropagation()event.preventDefault() 时的行为。

在第一种情况下,单击<div> 也会触发<a> 事件,将其移动到另一个页面。 event.stopPropagation() 无效。

如果我将event.stopPropagation() 更改为event.preventDefault(),当单击div 时,控制台会记录“div”<a> 不会触发任何事件,但复选框停止工作。所以event.preventDefault() 会影响一个子元素。

我在这里缺少什么?

.html

<a href="#" target="_blank">
  <div>
    <input type="checkbox"/>
  </div>
</a>

.js

var div = document.querySelector('div');

div.addEventListener('click', function(event) {
  event.stopPropagation();
  // event.preventDefault(); # second case
  console.log('div');
});

.css(只是为了更容易在屏幕上看到)

a {
  display: block;
  background: black;
  width: 300px;
  height: 100px;
}

div {
  background: red;
  width: 50px;
  height: 50px;
}

【问题讨论】:

  • 可能,尝试使用event.stopImmediatePropagation(),这样它会立即停止传播。检查这个 - stopImmediatePropagation
  • @TelmanAgababov 没有成功,但还是谢谢。

标签: javascript html


【解决方案1】:

event.preventDefault() 将阻止 href 和 checkbox 触发它们的默认事件,因为它是一个冒泡事件。

“当一个事件被分派给一个参与树的对象(例如一个元素)时,它也可以到达该对象的祖先上的事件侦听器。首先调用捕获变量设置为 true 的所有对象的祖先事件侦听器,以树顺序。其次,调用对象自己的事件侦听器。最后,只有当事件的气泡属性值为 true 时,才会再次调用对象的祖先事件侦听器,但现在以相反的树顺序。 - https://dom.spec.whatwg.org/#dom-event-preventdefault

当您使用event.stopPropagation() 时,您将阻止任何父母(或孩子,如果冒泡 = true)收到它的事件通知。这不会阻止它的默认事件被触发。

要检查事件是否正在冒泡,您可以使用var x = event.bubbles; console.log(x);

编辑:这是一个如何结合使用 event.preventDefault()event.stopPropagation() 的示例 -

var div = document.querySelector('div');
var a = document.querySelector('a');
a.addEventListener('click', function(event){
    event.preventDefault();
});
div.addEventListener('click', function(event) {
  event.stopPropagation();
  console.log('div');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" target="_blank">
  <div>
    <input type="checkbox"/>
  </div>
</a>

这将防止附加到&lt;a&gt; 的点击事件到达&lt;div&gt; 之外的任何内容

&lt;a&gt;&lt;div&gt;&lt;input&gt;&lt;/div&gt;&lt;/a&gt; 是一个元素。

&lt;div&gt;&lt;input&gt;&lt;/div&gt; 也是一个元素。这意味着当stopPropagation() 用于&lt;input&gt; 时,&lt;input&gt; 的点击处理程序将是唯一继续工作的处理程序。

stopPropagation(); 作用于点击处理程序事件,而不是默认浏览器事件。因此,当您停止在 &lt;input&gt; 元素上传播时, &lt;a&gt; 仍然会重定向用户,因为这是默认的浏览器事件。

但是,console.log('a fired.');console.log('div fired'); 不会触发,因为它们是点击处理程序,而不是默认浏览器事件。

preventDefault(); 阻止执行任何默认浏览器操作,而不是单击处理程序。

由于&lt;a&gt;&lt;div&gt;&lt;input /&gt;&lt;/div&gt;&lt;/a&gt; 是一个元素, 当您在&lt;a&gt; 上使用preventDefault(); 时,它将阻止附加到&lt;a&gt; &lt;div&gt;&lt;input /&gt; 的任何默认浏览器操作触发。

因此,当您将preventDefault() 添加到&lt;input /&gt; 并尝试单击它时,它的状态不会改变,但在单击&lt;a&gt; 时,&lt;a&gt; 链接仍将按预期工作。

var input = document.querySelector('div');
var a = document.querySelector('a');
var div = document.querySelector('a');

a.addEventListener('click', function(event){
    //event.preventDefault();
    //event.stopPropagation();
    console.log('a fired.');
});

div.addEventListener('click', function(event) {
  //event.preventDefault();
  //event.stopPropagation(); 
  console.log('div fired.');
});

input.addEventListener('click', function(event) {
  event.preventDefault();
  //event.stopPropagation(); 
  console.log('input fired');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- <a><div><input></div></a> is ONE element. -->
<a href="#" target="_blank" style="border:solid 1px #ccc;background:green;">this is a link
    <!-- <div><input></div> is also ONE element. This means when stopPropagation() is used on this element, all click handler events within this element will not trigger, but <a></a> will -->
  <div style="border: solid 1px #2779aa;">
    <input type="checkbox"/>
  </div>
</a>

【讨论】:

  • 感谢@Inkdot 的回答,但我不明白你对preventDefault() 的看法。单击复选框,冒泡事件按此顺序发生input &gt; div &gt; a,对吗?但是 div 上有一个 e.preventDefault(),所以,据我所知,应该防止默认行为从 div 开始,而不更改输入。关于您的示例,我想做的恰恰相反,如果直接单击链接,则使 &lt;a&gt; 链接有效,而单击事件在 div 内发生,但不选择复选框。
  • 你不明白,因为我犯了一个错误。我会更正并解释。
  • @rougeth 我希望编辑后的答案能回答您可能仍有的任何问题,并消除对这两种方法的任何困惑。代码示例应该为您提供所需的内容。
  • 知道了!现在一切都说得通了!非常感谢。
  • 为什么 child 上的 preventDefault 也会停止复选框的默认行为?它不应该只阻止孩子的默认行为吗?
猜你喜欢
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多