查找没有特定祖先的后代元素

时间:2015-02-20 17:07:55

标签: jquery jquery-selectors

我希望能够选择一个元素并找到具有特定类的所有后代元素,但不包含在类似的父元素中。很难描述:

HTML:

<div class="js-test js-1">
    <div class="b">1</div>
    <div class="b">1</div>
    <div class="d">
        <div class="b">1</div>        
    </div>
    <div class="js-test js-2">
        <div class="b">2</div>
        <div class="b">2</div>
        <div class="b">2</div>
        <div class="d">
            <div class="b">2</div>        
        </div>
        <div class="js-test js-3">
            <div class="b">3</div>
            <div class="b">3</div>
            <div class="b">3</div>
            <div class="b">3</div>
            <div class="d">
                <div class="b">3</div>        
            </div>
        </div>
    </div>
</div>

尝试jQuery:

$(document).ready(function(){
    function test(element)
    {
        var test2 = element.find('.b :not(.js-test .b)');
        console.log(test2.length);
    }

    console.clear();
    test($('.js-1'));
    test($('.js-2'));
    test($('.js-3'));
});

预期结果:

  

3

     

4

     

5

实际结果:

  

0

     

0

     

0

JsFiddle Example

4 个答案:

答案 0 :(得分:1)

您必须进行一些过滤才能仅计算.b出现最近.js-test等于element的事件:

element.find('.b').filter(function() {
    return $(this).closest('.js-test').is(element);
}).length;

Here's a fiddle

答案 1 :(得分:1)

选择器.b :not(.js-test .b)查找不是.b元素的.js-test .b元素的后代。这个选择器的问题有两个:

  • 每个.b元素都是.js-test元素的后代。这包括立即嵌套在您正在测试的每个上下文.b元素中的.js-test个元素。

  • 第一个.b:not()之间的空格代表一个后代选择器,这也意味着由:not()表示的元素很可能是{{1}完全和仍然匹配。

    但是您的:not(.b)元素都没有任何元素后代,这就是为什么所有测试结果都为零的真正原因。

由于您无法直接创建与上下文元素(参数.b)对应的选择器,您需要编写自定义过滤器函数,如billyonecan提出的那样,并根据是否进行过滤它最接近的element祖先是上下文元素。

答案 2 :(得分:0)

尝试

// descendant `.b` of `element`,
// descendant `.b` of `element`, not `.b`, not `.js-test`
var test2 = element.find("> .b, > :not(.b):not(.js-test) .b");

jsfiddle http://jsfiddle.net/ku2pdn2j/4/


    $(document).ready(function(){
        function test(element) {
            var test2 = element.find("> .b, > :not(.b):not(.js-test) .b");
            console.log(test2.length, test2);
        }
        
        console.clear();
        test($('.js-1'));
        test($('.js-2'));
        test($('.js-3'));
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
   <div class="js-test js-1">
        <div class="b">1</div>
        <div class="b">1</div>
        <div class="d">
            <div class="b">1</div>        
        </div>
        <div class="js-test js-2">
            <div class="b">2</div>
            <div class="b">2</div>
            <div class="b">2</div>
            <div class="d">
                <div class="b">2</div>        
            </div>
            <div class="js-test js-3">
                <div class="b">3</div>
                <div class="b">3</div>
                <div class="b">3</div>
                <div class="b">3</div>
                <div class="d">
                    <div class="b">3</div>        
                </div>
            </div>
        </div>
    </div>

答案 3 :(得分:0)

我最终使用了与billyonecan的回答类似的内容:

$(document).ready(function(){
    function test(element)
    {
        var all = element.find('.b');
        var exclude = element.find('.js-test .b');
        var test = all.not(exclude);
        console.log(test.length);
    }

    console.clear();
    test($('.js-1'));
    test($('.js-2'));
    test($('.js-3'));
});

实际结果:

  

3

     

4

     

5

预期应用程序的结果集非常小,我不相信这里的任何解决方案之间的性能有任何显着差异。