如何选择先前使用以下过滤的后代元素:not或.not()

时间:2012-10-19 18:45:19

标签: jquery jquery-selectors

猜猜以下HTML DOM的正文片段:

...
<div class="entry">
    <div class="evil">
        <div class="some-other-class">
            <pre>My foo text</pre>
        </div>
    </div>
</div>
<div class="entry">
    <div class="nice">
        <pre>My nice text</pre>
    </div>
</div>
...

使用jQuery我想选择属于<pre>类型的父元素的所有div.entry元素,不是div.evil的后代。更确切地说:我想将特定的类应用于那些“非邪恶的”<pre>元素。

我使用了:not选择器过滤器以及.not()方法来构建链,以便在应用类之前选择适当的子集和后代元素,如下所示:

$("div.entry div:not(.evil) pre").addClass("pretty");

另外:

$("div.entry").not("div.evil").find("pre").addClass("pretty")

这两个变体导致匹配所有pre元素,包括那些带有“邪恶”父div的那些!

然而,当我选择一个直接的父级加上类和这样的孩子时:

$("div.entry div:not(.some-other-class) > pre").addClass("pretty");

它按预期工作。首先,我认为我误解了使用element1 element2的后代元素选择。使用链式过滤器方法没有成功,但证明了其他东西必定是错误的。

问题本身听起来并不难,但它现在让我疯狂。

任何想法是否以及为何我的选择方式可能都是错的?

3 个答案:

答案 0 :(得分:3)

我建议:

$('div.entry pre').filter(function(){
    return !$(this).closest('div.evil').length
});

JS Fiddle demo

对我来说,优点是你只需选择所有 pre元素,然后根据(相当)简单的父评估减少这些元素。替代方法同样有效,这只是......我个人的偏好。

答案 1 :(得分:3)

保持简单:

$('div.entry pre:not(div.evil pre)');

在这里:jsfiddle demo

注意

那么,为什么

$("div.entry div:not(.evil) pre");

不起作用?

当您要求div:not(.evil)时,jQuery人会返回div.some-other-class以及div.nice,以便最终选择器为:

$("div.entry div.some-other-class pre, div.entry div.nice pre");

甚至与pre的后代相匹配,后者是坏的,坏的,div.evil

答案 2 :(得分:2)

您可以使用:has选择器:

$("div.entry:not(:has(.evil)) pre").addClass("pretty");

http://jsfiddle.net/7BNQN/

或者:

$('div.entry').not(':has(.evil)').find('pre').addClass("pretty");