jQuery点击除子级div外的父级div事件

29

我有以下HTML:

<div class="server" id="32">
  <a>Server Name</a>
  <div class="delete-server">X</div>
</div>

我想让用户点击“server” div 后出现一个编辑对话框。但问题在于只是这样做:

 $(".server").click(function () {
     //Show edit dialog
 });

因为如果点击删除按钮(X),会弹出编辑对话框,所以不起作用。如何使整个div server 具有点击事件,除了 delete-server div。


你应该知道你接受的答案毫无意义地使用了委托事件。你可以阅读 on 文档 了解它的作用。 - gdoron
@gdoron - 你能否提供你所声称的事件委托更慢的来源?据我所知,事件委托做的事情与你所做的相同,只是在幕后进行;它会检查目标元素是否与给定的选择器匹配。虽然我可能错了,但我很想得到启发。 - Joseph Silber
相关内容:https://dev59.com/S2cs5IYBdhLWcg3woVh-#12690357 - Adriano
4个回答

37
$(".server").on('click', ':not(.delete-server)', function (e) {
     e.stopPropagation()
     // Show edit dialog
});

这是 fiddle 链接: http://jsfiddle.net/9bzmz/3/


注意,点击服务器名称时为什么会触发两次警报?http://jsfiddle.net/9bzmz/1/ - Justin
@Justin 当你单击“服务器名称”时,它是否在你的页面上显示两个警报框? - Peeyush
@qwertymk 我认为这是由于事件冒泡引起的,我说得对吗? - Peeyush
1
它在我的情况下完全与应该的相反。在不应该出现的类中显示警报框,而在应该出现的地方则没有显示。为什么?:o - Marek
@Marek 我也遇到了同样的问题。 - Myat Min Soe
显示剩余2条评论

26

只需检查触发事件的元素:

$(".server").click(function(e) {
    if (!$(e.target).hasClass('delete-server')) {
        alert('Show dialog!');
    }
});​

LIVE DEMO


当单击 X 时仍然会看到编辑对话框弹出,我认为这是因为点击事件在 .server 上触发,所以它不知道子 div .delete-server - Justin
@Justin,请查看更新后的答案。你应该知道,你接受的答案创建了一个“委托事件”而不是“直接事件”,这会更慢,并且没有理由这样做。委托事件应该用于动态更改DOM结构。 - gdoron
你能否提供一个支持你所说的事件委托比较慢的来源吗?据我所知,事件委托和你手动绑定事件的效果是一样的,只不过它是在后台进行的;它会检查目标元素是否匹配给定的选择器。虽然我可能错了,但我很愿意接受启示。 - Joseph Silber

11

有一种替代的解决方法:

$(".server").click(function () {
    // show edit dialog
});
$(".delete-server").click(function (event) {
    // show delete dialog for $(this).closest(".server")
    event.stopPropagation();
});

确保在.delete-server上触发的点击事件不会冒泡到父元素。


+1 不错的方法,虽然它使用了两个处理程序,但可以通过检查“target”元素来完成。请查看此链接 - gdoron
@gdoron 是的,但这样会有什么优雅之处呢?这将导致一个单一的事件处理程序,并在其中使用if/switch检查来确定事件实际上应该执行什么操作。我认为这相当不好。 - Tomalak
嗯...其实没有什么错的方法,我更喜欢我的。每种方法都比那个毫无意义地使用委托事件的被接受答案更好... :) - gdoron
从实用角度来看,所有有效的东西都是好的。基于这一点,被接受的答案并不比你的或我的差。从架构上讲,最好将独立的关注点分开处理。将您的方法推向极端,会得到一个带有巨大switch语句的大型$(“body”).click()事件处理程序 。我认为我们可以同意这将很丑陋。在较小的规模上做相同的事情仍然很丑陋。 :) - Tomalak
2
所接受的答案解决了所提出的问题,但此解决方案的好处是还可以防止位于 <div class="delete-server"></div> 元素中的潜在子元素冒泡。 - Ian Lunn

0

只有这个对我有效。

js_object 是 jQuery 对象,用于元父级,例如 $('body')

jq_object.on('click', '.js-parent :not(.js-child-1, .js-child-2)', function(event) {
    //your code
});

jq_object.on('click', '.js-child-1', function(event) {
    //your code
});

jq_object.on('click', '.js-child-2', function(event) {
    //your code
});

针对您的情况:

服务器 - js-parent

删除服务器 - js-child-1

jq_object.on('click', '.server :not(.delete-server)', function(event) {
    //your code
});

jq_object.on('click', '.delete-server', function(event) {
    //your code
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接