当用户点击可用的div时,我正在克隆div标签。克隆后,我点击div标签后插入它。这个新的div标签也有交叉链接来删除它。但是,当我点击交叉链接时,它会删除该特定div。这意味着它正在发挥作用。现在我还有一个名为foo
的函数。添加和删除div标签时调用此方法。但是当我点击删除链接时,这个foo函数被调用两次。我知道它的原因是因为我将click事件附加到删除链接的父节点并删除链接本身,因此它被调用两次。但是如何在添加和删除div元素时调用它一次?
这是我的JSFIDDLE
HTML:
<div class="container">
<div class="bx"></div>
</div>
这是js
$('body').on('click', '.bx', function (e) {
var clone = $(this).clone();
clone.append('<a class="bx-del" href="#">X</a>');
$(this).after(clone);
foo();
});
$('body').on('click', '.bx-del', function (e) {
e.preventDefault();
$(this).parent().remove();
foo();
});
function foo() {
console.log('foo');
}
答案 0 :(得分:2)
我原来的回答是:
假设.bx-del
位于.bx
内(最好在问题中添加html),那么在e.stopPropagation()
回调中添加.bx-del
应该有效。
E.g。
$('body').on('click', '.bx-del', function (e) {
e.preventDefault();
e.stopPropagation();
$(this).parent().remove();
foo();
});
有人指出,这两个事件实际上都附加在身体上并作为委托事件运行。这个解决方案似乎有效,但问题是它是否可靠。这里的问题是委托事件的运行顺序是什么?他们总是跑步&#34;深度第一&#34;或根据他们被添加的顺序或什么?在我看来,首先运行它们是最合乎逻辑的,但性能方面的考虑也将在这里发挥重要作用。
我一直无法找到任何有关此问题的硬文档。 jQuery .on() documentation说
可以解释为,但也可以解释授权概念。jQuery将事件从事件目标起泡到元素所在的位置 处理程序附加(即最里面到最外面的元素)和 为该路径上匹配的所有元素运行处理程序 选择器。
因此,在我看来,对原始问题更安全的解决方案是将两个舔事件合并为一个:
$('body').on('click', '.bx', function (e) {
var t = $(e.target);
if( t.hasClass('bx-del') || t.closest('.bx-del').length > 0){
e.preventDefault();
t.closest('.bx').remove();
foo();
} else {
var clone = $(this).clone();
if( $('.bx-del', clone).length == 0 ){
clone.append('<a class="bx-del" href="#">X</a>');
}
$(this).after(clone);
foo();
}
});
(我还修复了这样,用删除按钮克隆div并不会添加第二个删除按钮。)
答案 1 :(得分:1)
这是(docs)的 event.stopPropagation()
。它可以防止事件冒泡进入DOM树。如果您将e.stopPropagation()
添加到删除链接点击处理程序,它将不会冒泡到包含它的div并在那里触发点击处理程序:
正如评论中指出的那样,这是不正确的,即使它似乎正常工作。两个事件处理程序都附加到正文,并且只能通过“诡计”来实现。运行特定元素。该事件已经在body元素中,因此不会再冒泡。此外,event.stopPropagation()
不应该阻止其他处理程序执行,尽管它们现在无论如何都会这样做。这里使用的正确函数是event.stopImmediatePropagation()
(docs at jquery)。
$('body').on('click', '.bx-del', function (e) {
e.preventDefault();
e.stopImmediatePropagation();
$(this).parent().remove();
foo();
});
答案 2 :(得分:0)
因为当事件已经传播到<body>
标记并且您的事件都在<body>
标记上时,您无法停止传播到<body>
标记,我建议您只删除删除事件处理程序直接删除X对象,不使用该事件处理程序的传播。然后,您可以停止该点击的播放,这样父母就不会看到它。在你的情况下,这很容易。
工作演示:http://jsfiddle.net/jfriend00/7CDNG/
$('body').on('click', '.bx', function (e) {
var clone = $(this).clone();
clone.append('<a class="bx-del" href="#">X</a>');
$(this).after(clone);
clone.find('.bx-del').on('click', function(e) {
$(this).parent().remove();
foo();
// stop propagation and prevent default
return false;
})
foo();
});
function foo() {
console.log('foo');
}
或者,您可以将.bx
处理程序放在document
对象上,将.bx-del
处理程序放在body
对象上,然后就可以停止传播到{{1来自document
处理程序的对象。但是,在这种情况下,将删除事件直接附加到删除对象并且不使用委托事件处理以避免对.bx-del
事件的任何可能的错误解释更为清晰。
显然,其他答案在一个click
事件处理程序上使用.stopPropagation()
以阻止其他事件被触发。这是来自body
的jQuery文档的引用:“我认为你很幸运。这是直接从jQuery文档中获取stopPropagation():”请注意,这不会阻止其他处理程序运行中的元素。“由于这两个事件处理程序都在.stopPropagation()
对象上,因此使用body
来阻止另一个运行时,这似乎不是一个明智和安全的举动。这是我的看法该技术不安全,并不是解决这个问题的概念上正确的方法。