为什么jquery:not()选择器不像我期望的那样工作?

时间:2013-01-01 01:14:35

标签: javascript jquery css3

我正在尝试设置一个事件,当点击没有.four类的任何内容时触发该事件。但是,即使我使用.four,点击e.stopPropagation()类的内容时也会触发。

$("html").one("click", ":not(.four)", function(e){
   e.stopPropagation();
   console.log("Something without class 'four' was clicked that had class: " + $(e.srcElement).attr("class") );
});

jsFiddle Demo

这也不起作用:

$("html").not('.four').on("click", function(e){

两个输出:Something without class 'four' was clicked that had class: four

我在使用:not()时遇到了很多麻烦,我怀疑它可能与我的浏览器支持CSS3 :not()现在有很多关系,但我仍然无法理解这个简单的问题。

4 个答案:

答案 0 :(得分:6)

您的代码:

$("html").one("click", ":not(.four)", function(e){
    e.stopPropagation();
    // other code
});

为click事件类型设置全局事件委派。这意味着只要在页面上的任何元素触发click事件,jQuery就会检查该元素是否与提供的选择器匹配 - ":not(.four)" - 如果匹配,jQuery将调用处理程序关于那个元素。

当您点击.four元素时会发生这种情况:

  1. 触发click事件的原始元素显然是.four元素。 jQuery检查该元素是否与":not(.four)"选择器匹配。因为它没有,所以在该元素上调用处理程序

  2. 点击事件冒泡DOM树。由于此click事件的传播尚未取消,因此事件将触发下一个元素,即原始元素的父元素 - 演示中的.two元素。同样,jQuery检查元素是否与选择器匹配。既然如此,就会在该元素上调用处理程序。

  3. 如您所见,即使您点击.four元素,也会调用您的处理程序 。为了防止在单击.four元素时执行代码,您必须在处理程序中明确检查 - 基本上是Jason的解决方案。

答案 1 :(得分:2)

正如ŠimeVidas所指出的,这是理想的解决方法:

function doThisOnce(e) {
   e.stopPropagation();

   if(!$(this).is(".four")){
        console.log("Something without class 'four' was clicked that had class: " + $(e.srcElement).attr("class"));
        $(".one").addClass("pretty");
    }
    else {
        // need to rebind the click event
        $(document).one("click", "*", doThisOnce);
    }
}
$(document).one("click", "*", doThisOnce);

答案 2 :(得分:2)

这是我想要贡献的解决方案。把这个听众放在另一个旁边:

$("html").one("click", ".four", function(e){
       e.stopPropagation();
});
$("html").one("click", function(e){
    // other code
});

它会阻止.four上的传播,并“窃取”或“捕获”它从冒泡到另一个侦听器。让“捕手”监听器处于比另一个更低的级别可能会有所帮助,具体取决于它是否在另一个之前冒泡。

最后看到jsFiddle demo,正在工作!

答案 3 :(得分:0)

以下是使用事件target

的另一种方法
$(document).one("click", function(e){
    if( ! $(e.target).closest('.four').length ){
         console.log("Something without class 'four' was clicked that had class: " + $(e.srcElement).attr("class") );
     }
});

closest()将匹配类的子元素以及类元素本身