对链接内的元素执行stopPropagation / preventDefault行为

时间:2017-02-21 22:29:36

标签: javascript html

我正在尝试了解<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;
}

1 个答案:

答案 0 :(得分:0)

event.preventDefault()会阻止href和复选框触发默认事件,因为它是冒泡事件。

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

当您使用event.stopPropagation()时,您正在阻止任何父级(或者如果bubbling = true则为子级)被通知其事件。这不会阻止它被触发的默认事件。

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

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

&#13 ;
&#13;
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');
});
&#13;
<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>
&#13;
&#13;
&#13;

这会阻止附加到<a>的点击事件超出<div>

以外的任何内容

<a><div><input></div></a>是一个元素。

<div><input></div>也是一个元素。这意味着在stopPropagation()上使用<input>时,<input>的点击处理程序将是唯一继续有效的处理程序。

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

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

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

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

所以当您将preventDefault()添加到<input />并尝试点击它时,它的状态不会被更改,但<a>链接仍会发挥作用按照<a>点击时的预期。

&#13;
&#13;
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');
});
&#13;
<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>
&#13;
&#13;
&#13;