链接内元素的 stopPropagation/preventDefault 行为 [英] stopPropagation/preventDefault behavior on an element inside a link
问题描述
我试图了解当 中的元素具有
event.stopPropagation()
或 event.preventDefault()
.
在第一种情况下,点击
事件,将其移动到另一个页面.event.stopPropagation()
无效.如果我将 event.stopPropagation()
更改为 event.preventDefault()
,则在 div 中单击时,控制台会记录 "div", 不会触发任何事件,但复选框停止工作.所以
event.preventDefault()
影响子元素.
我在这里缺少什么?
.html
<div><input type="checkbox"/>
</a>
.js
var div = document.querySelector('div');div.addEventListener('click', function(event) {event.stopPropagation();//event.preventDefault();# 第二种情况console.log('div');});
.css(只是为了更容易在屏幕上看到)
a {显示:块;背景:黑色;宽度:300px;高度:100px;}div {背景:红色;宽度:50px;高度:50px;}
event.preventDefault()
将阻止 href 和 checkbox 触发它们的默认事件,因为它是冒泡事件.
"当一个事件被分派到一个参与树的对象(例如一个元素)时,它也可以到达该对象的祖先上的事件监听器.首先,所有对象的祖先事件监听器的捕获变量设置为 true 被调用,以树顺序.其次,调用对象自己的事件侦听器.最后,只有当事件的气泡属性值为真时,才会再次调用对象的祖先事件侦听器,但现在以相反的树顺序调用."- https://dom.spec.whatwg.org/#dom-event-preventdefault
当您使用 event.stopPropagation()
时,您正在阻止任何父级(或子级,如果冒泡 = true)被通知其事件.这不会阻止它的默认事件被触发.
要检查事件是否冒泡,您可以使用 var x = event.bubbles;console.log(x);
edit:这是一个如何结合使用 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"/>
是一个元素.
也是一个元素.这意味着当 stopPropagation()
用于 时,
的点击处理程序将是唯一一个继续工作.
stopPropagation();
作用于点击处理程序事件,而不是默认浏览器事件.所以当你停止在 元素上传播时,
仍然重定向用户,因为这是默认浏览器事件.
但是,console.log('a fire.');
和 console.log('div fires');
不会触发,因为它们是点击处理程序,不是默认浏览器事件.
preventDefault();
阻止执行任何默认浏览器操作,而不是单击处理程序.
是一个元素,当您在 上使用
preventDefault();
时,它将阻止附加到 的任何默认浏览器操作.<div>
或 来自触发.
因此,当您将 preventDefault()
添加到 <input/>
并尝试单击它时,它的状态不会改变,但是 被点击时,> 链接仍将按预期运行.
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 被解雇了.');});div.addEventListener('click', function(event) {//event.preventDefault();//event.stopPropagation();console.log('div 被触发.');});input.addEventListener('click', function(event) {event.preventDefault();//event.stopPropagation();console.log('输入被触发');});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><!-- <a><div><input></div></a>是一个元素.--><a href="#" target="_blank" style="border:solid 1px #ccc;background:green;">这是一个链接<!-- <div><input></div>也是一个元素.这意味着当在这个元素上使用 stopPropagation() 时,这个元素内的所有点击处理程序事件都不会触发,但是 <a></a>将——><div style="border:solid 1px #2779aa;"><input type="checkbox"/>
I'm trying to understand the behavior when an element inside of a <a>
have a event.stopPropagation()
or event.preventDefault()
.
In the first case, clicking in the <div>
also fires the <a>
event, moving it to another page. event.stopPropagation()
has no effect.
If I change event.stopPropagation()
to event.preventDefault()
, when clicking in the div, the console logs "div", the <a>
does not fires any event BUT the checkbox stops working. So event.preventDefault()
affect a child element.
What I'm missing here?
.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 (just to make it easier to see on screen)
a {
display: block;
background: black;
width: 300px;
height: 100px;
}
div {
background: red;
width: 50px;
height: 50px;
}
event.preventDefault()
will prevent both the href and checkbox from firing their default events because it is a bubbling event.
"When an event is dispatched to an object that participates in a tree (e.g. an element), it can reach event listeners on that object’s ancestors too. First all object’s ancestor event listeners whose capture variable is set to true are invoked, in tree order. Second, object’s own event listeners are invoked. And finally, and only if event’s bubbles attribute value is true, object’s ancestor event listeners are invoked again, but now in reverse tree order." - https://dom.spec.whatwg.org/#dom-event-preventdefault
When you use event.stopPropagation()
you are preventing any parent (or child if bubbling = true) from being notified of it's event. This will not prevent it's default event from being fired.
To check if an event is bubbling you can use var x = event.bubbles; console.log(x);
edit: here's an example of how to use
event.preventDefault()
and event.stopPropagation()
in conjunction -
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>
This will prevent the click event attached to <a>
from reaching anything beyond <div>
<a><div><input></div></a>
is ONE element.
<div><input></div>
is also ONE element. This means when stopPropagation()
is used on <input>
the click handler for <input>
will be the only one which continues to work.
stopPropagation();
acts upon click handler events, not default browser events. So when you stop propagation on the <input>
element,
<a>
still redirects the user, because that is it's default browser event.
However, console.log('a fired.');
and console.log('div fired');
will not trigger as they are click handlers, not default browser events.
preventDefault();
prevents any default browser actions from being executed, not click handlers.
Since <a><div><input /></div></a>
is ONE element,
when you use preventDefault();
on <a>
it will prevent any default browser actions attached to <a> <div>
or <input />
from firing.
so when you add preventDefault()
to <input />
and try to click on it, it's state won't be changed, but the <a>
link will still function as intended when <a>
is clicked.
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>
这篇关于链接内元素的 stopPropagation/preventDefault 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!