我目前正在使用 jQuery 来制作可点击的 div,并且在这个 div 中我也有锚点。我遇到的问题是,当我点击一个锚点时,两个点击事件都在触发(对于 div 和锚点)。单击锚点时,如何防止 div 的 onclick 事件触发?
这是损坏的代码:
JavaScript
var url = $("#clickable a").attr("href");
$("#clickable").click(function() {
window.location = url;
return true;
})
HTML
<div id="clickable">
<!-- Other content. -->
<a href="http://foo.example">I don't want #clickable to handle this click event.</a>
</div>
事件冒泡到 DOM 中附加点击事件的最高点。因此,在您的示例中,即使您在 div 中没有任何其他显式可单击元素,div 的每个子元素也会将其单击事件在 DOM 中冒泡,直到 DIV 的单击事件处理程序捕获它。
有两种解决方案是检查谁实际发起了该事件。 jQuery 将 eventargs 对象与事件一起传递:
$("#clickable").click(function(e) {
var senderElement = e.target;
// Check if sender is the <div> element e.g.
// if($(e.target).is("div")) {
window.location = url;
return true;
});
您还可以将 click 事件处理程序附加到您的链接,在他们自己的处理程序执行后告诉他们 stop event bubbling:
$("#clickable a").click(function(e) {
// Do something
e.stopPropagation();
});
使用 stopPropagation 方法,看一个例子:
$("#clickable a").click(function(e) {
e.stopPropagation();
});
正如jQuery Docs所说:
stopPropagation 方法防止事件在 DOM 树中冒泡,防止任何父处理程序收到事件通知。
请记住,它不会阻止其他侦听器处理此事件(例如,一个按钮的多次单击处理程序),如果它不是所需的效果,则必须使用 stopImmediatePropagation
代替。
这是我为寻找非jQuery代码(纯javascript)的每个人提供的解决方案
document.getElementById("clickable").addEventListener("click", function( e ){
e = window.event || e;
if(this === e.target) {
// put your code here
}
});
如果单击父母的孩子,您的代码将不会被执行
window.event
:developer.mozilla.org/en-US/docs/Web/API/Window/event。如果您能抽出时间,如果您能评论一下您为什么使用 window.event
,我将不胜感激(也许这是 2015 年存在的问题,或者我无法理解原因)。
如果您在任何情况下都不打算与内部元素交互,那么 CSS 解决方案可能对您有用。
只需将内部元素设置为 pointer-events: none
在你的情况下:
.clickable > a {
pointer-events: none;
}
或一般针对所有内部元素:
.clickable * {
pointer-events: none;
}
在使用 ReactJS 进行开发时,这个简单的 hack 为我节省了很多时间
可以在此处找到浏览器支持:http://caniuse.com/#feat=pointer-events
你也可以试试这个
$("#clickable").click(function(event) {
var senderElementName = event.target.tagName.toLowerCase();
if(senderElementName === 'div')
{
// do something here
}
else
{
//do something with <a> tag
}
});
内联替代方案:
<div>
<!-- Other content. -->
<a onclick='event.stopPropagation();' href="http://foo.example">I don't want #clickable to handle this click event.</a>
</div>
如果可点击 div 中有多个元素,则应执行以下操作:
$('#clickable *').click(function(e){ e.stopPropagation(); });
使用 return false;
或 e.stopPropogation();
将不允许执行更多代码。它会在此时停止流动。
当 this
不可用(React 等)时,我与 ev.currentTarget
进行比较。
$("#clickable").click(function(e) {
if (e.target === e.currentTarget) {
window.location = url;
return true;
}
})
这是使用 Angular 2+ 的示例
例如,如果您想在用户单击模态组件外部时关闭它:
// Close the modal if the document is clicked.
@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
this.closeModal();
}
// Don't close the modal if the modal itself is clicked.
@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
event.stopPropagation();
}
var inner = document.querySelector("#inner"); var external = document.querySelector("#outer"); inner.addEventListener('click',innerFunction); outer.addEventListener('click',outerFunction); function innerFunction(event){ event.stopPropagation(); console.log("内部函数"); } function outerFunction(event){ console.log("Outer Function"); }
如果它是在内联上下文中,在 HTML 中试试这个:
onclick="functionCall();event.stopPropagation();
e.stopPropagation()
是一个正确的解决方案,但如果您不想将任何事件处理程序附加到您的内部锚点,您可以简单地将此处理程序附加到您的外部 div:
e => { e.target === e.currentTarget && window.location = URL; }
您可以检查目标是否不是您的 div 元素,然后在父级上发出另一个单击事件,之后您将从句柄“返回”。
$('clickable').click(function (event) {
let div = $(event.target);
if (! div.is('div')) {
div.parent().click();
return;
}
// Then Implement your logic here
}
要将某些子元素指定为不可点击,请编写 css 层次结构,如下例所示。
在此示例中,我停止传播到具有类“.subtable”的表内的 td 内 tr 内的任何元素 (*)
$(document).ready(function()
{
$(".subtable tr td *").click(function (event)
{
event.stopPropagation();
});
});
如果有人在使用 React 时遇到了这个问题,我就是这样解决的。
scss:
#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }
#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }
组件的渲染():
render() {
...
return (
<div id='loginBackdrop' onClick={this.props.closeLogin}>
<div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
... [modal content] ...
</div>
</div>
)
}
通过为子模式(内容 div)添加 onClick 函数,可以防止鼠标单击事件到达父元素的“closeLogin”函数。
这对我有用,我能够用 2 个简单的 div 创建模态效果。
ignoreParent() 是一个纯 JavaScript 解决方案。
它作为一个中间层,将鼠标点击的坐标与子元素的坐标进行比较。两个简单的实现步骤:
1. 将 ignoreParent() 代码放在您的页面上。
2. 代替父母原来的onclick="parentEvent();",写成:
onclick="ignoreParent(['parentEvent()', 'child-ID']);"
您可以将任意数量的子元素的 ID 传递给函数,并排除其他元素。
如果您单击其中一个子元素,则不会触发父事件。如果您单击了父元素,但没有单击任何子元素 [作为参数提供],则会触发父事件。
如果单击子元素,则事件会冒泡到父元素和 event.target !== event.currentTarget。
因此,在您的函数中,您可以检查并提前返回,即:
var url = $("#clickable a").attr("href");
$("#clickable").click(function(event) {
if ( event.target !== event.currentTarget ){
// user clicked on a child and we ignore that
return;
}
window.location = url;
return true;
})
这就是你要找的
mousedown
事件。这适用于每个 DOM 元素,以防止像这样的 javascript 焦点处理程序:
$('.no-focus').mousedown(function (e) {
e.prevenDefault()
// do stuff
}
在 vue.js
框架中,您可以使用如下修饰符:
<span @mousedown.prevent> no focus </span>
请注意,在输入上使用将阻止文本选择处理程序
所有的解决方案都很复杂并且属于 jscript。这是最简单的版本:
var IsChildWindow=false;
function ParentClick()
{
if(IsChildWindow==true)
{
IsChildWindow==false;
return;
}
//do ur work here
}
function ChildClick()
{
IsChildWindow=true;
//Do ur work here
}
添加 a
如下:
<a href="http://foo.example" onclick="return false;">....</a>
或来自 #clickable
的点击处理程序的 return false;
,例如:
$("#clickable").click(function() {
var url = $("#clickable a").attr("href");
window.location = url;
return false;
});
<a onclick="return false;" href="http://foo.example">I want to ignore my parent's onclick event.</a>
不定期副业成功案例分享
if( e.target !== this) return;
比在子级中使用e.stopPropagation()
更好,因为您永远不知道其他人是否将某些处理程序附加到子级,或者库是否必须将处理程序附加到子级(而且您不想搞砸与图书馆代码)。这是一个更好的关注点分离。if( e.target !== this) return;
检查放入父级意味着如果单击该父级的任何其他没有自己的 onClick 处理程序的子级,则不会发生任何事情。因此,对于您有例如可点击的父 div 的情况,它是无用的。e.stopPropagation()
但是工作正常。