【问题标题】:jQuery filtering selector to remove nested elements matching patternjQuery过滤选择器以删除匹配模式的嵌套元素
【发布时间】:2011-03-06 23:35:08
【问题描述】:

鉴于此示例标记(假设在 .outer.inner 之间有随机数量的元素:

<div class="outer">
    <div>
        <div>
            <div class="inner"></div>
        </div>
    </div>
</div>

我可以设置 jQuery 来选择外部和内部 div,如下所示:

$outer = $('.outer');
$inner = $outer.find('.inner')

工作正常。

但是,假设我想允许这个逻辑的无限嵌套,所以我可能有这个:

<div class="outer"> div a
    <div class="inner"> div b
        <div class="outer"> div c
            <div class="inner"> div d </div>
        </div>
    </div>
</div>

在这种情况下,当通过.outer 选择 div a 时,我只想将它与 div b 匹配。换句话说,我想排除嵌套.outer 祖先的祖先。

我希望在它们的嵌套级别中包含外部和内部的配对。

我希望.filter() 能够成功,但想不出一个可以普遍适用于无限嵌套模式的选择器。使用过滤器是否可行?或者甚至是直接选择器模式?

更新:

我认为这样的事情可能会起作用,但不确定如何(或是否允许)在选择器中引用“this”:

$outer = $('.outer');
$inner = $outer.not('this .outer').find('.inner')

更新 2:

我应该一开始就提到这一点:.inner 将始终是.outer 的后代,但不一定是直系孩子。

更新 3:

这里有一些可以使用的 HTML 测试示例。在每种情况下,我都希望能够选择 .outer 并将其包含在自身和嵌套的外部之间的 .inner 配对。为清楚起见,我为每个 div 添加了名称(outer-x 与 inner-x 对)

//sample 1
<div class="outer"> outer-a
    <div>
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div class="inner"> inner-b </div>
            </div>
        </div>
    </div>
    <div>
        <div class="inner"> inner-a </div>
    </div>
</div>

//sample 2
<div class="outer"> outer-a
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div>
                    <div class="inner"> inner-b </div>
                </div>
            </div>
        </div>
</div>

//sample 3
<div class="outer"> outer-a
        <div class="inner"> inner-a
            <div class="outer"> inner-b
                <div class="inner"> inner-b
                    <div class="outer"> outer-c 
                        <div class="inner"> inner-c</div>
                    </div>
                </div>
            </div>
        </div>
</div>

//bonus sample (we're trying to avoid this)
<div class="outer"> outer-a
        <div class="inner outer"> inner-a outer-b
            <div class="inner"> inner-b </div>
        </div>
</div>

更新 4

我想我最终走上了与 gnarf 类似的道路。我最终得到了这个:

var $outer = $('.outer');
var $inner = $outer.find('.inner').filter(function(){
    $(this).each(function(){
        return $(this).closest('.outer') == $outer; 
  });                                                                  
});

我在正确的轨道上吗?它不起作用,所以我认为我仍然有一些逻辑错误。

【问题讨论】:

  • 这没有意义 - 即使你匹配第一个嵌套并且只删除它 - 它的孩子无论如何都会被删除

标签: jquery jquery-selectors


【解决方案1】:

这是另一种选择。假设你有.outero,这将选择它下面的所有inners:

o.find('.inner').not(o.find('.outer .inner'))

它应该与 gnarf 的答案相同,但更简单一些。

首先,它会找到这个outer下的所有inners。
接下来,删除所有属于其他outers 后代的inners

交互工作示例:http://jsfiddle.net/Zb9gF/

.filter() 相比,使用此方法的选择器性能似乎要好得多:http://jsperf.com/selector-test-find-not

【讨论】:

  • 太棒了!像往常一样,答案比我最终走的路要简单。我一直在为将缓存对象与 css 选择器组合所需的语法而苦苦挣扎,而我没有想到 find() 逻辑。谢谢!
  • 谢谢!顺便说一句,这个问题很有趣也很有挑战性,花了很多功夫才弄到这个简单的路线……
  • 不错的优化,希望我能先想到它 :) -- 昨天只是在玩 .not()this answer 的用处。
  • 为什么要先找外层?为什么不只寻找内部,然后获得最接近的外部?另见我的评论
  • 嘿,这个问题让我有资格获得银牌jQuery 徽章!
【解决方案2】:

不知道为什么不先选择.inner,然后得到closest.outer

$inner = $('.inner'); $outer = $inner.closest('.outer');

如果某些内部块根本不在外部块中,请改用第一行

$inner = $('.outer .inner');

【讨论】:

  • 这里的问题是另一个方向。给定一个 outer,你如何找到它的inner div?
  • 见。我的问题是为什么不去其他方向。给定 .outer 后,Kobi 的答案非常完美。但是,如果您只需要为所有外部获取所有内部-也许您可以从头开始可以这么说
【解决方案3】:

如果假设正确,您想选择.outer 下方的所有.inner,除非中间有.outer,否则以下可能会起作用(未经测试):

$('.outer:not(.inner):has(:not(.outer) .inner:not(.outer), > .inner:not(.outer))');

http://jsfiddle.net/cEwBT/1/ 的 OP 示例 HTML 测试后更新

【讨论】:

  • 你的假设是正确的。但是,该示例不起作用。我首先缓存“外部”,然后想要找到所有不是嵌套外部子级的内部。问题是我缓存的外部 is 是一个 .outer 所以会排除它自己。
【解决方案4】:

如果.inner 始终是.outers 的直接子代 - children() 可能是您最好的选择(jasongetsdown 的回答)

如果你需要看起来更深的东西,你可以这样做:

var $outer = $('.outer').first(); // grab the first .outer
$outer.find('.inner').filter(function() {
    // only if the closest parent .outer is the same as the .outer we are looking in
    return $(this).closest('.outer').get(0) == $outer.get(0);
}).css('border','1px solid #000');

jsfiddle demo

【讨论】:

  • @gnarf...我认为这也接近我的想法。我在我的帖子中添加了一个更新,它也使用了过滤器功能。我的不行,所以接下来试试你的语法!
  • 顺便说一下,一小时前 +1,不错。我很确定你是对的,这似乎是正确的逻辑。
【解决方案5】:

你可以使用一些 css 魔法:

$('.outer>.inner')

Shold 只给你第一级.inner 元素。 :)

【讨论】:

  • 该选择器将匹配.inner's
【解决方案6】:
$('.outer').children('.inner');

这将选择位于outer 正下方的任何inner。我不太清楚您要选择哪个 div。是a、b、c还是d?将一个叫做外部的东西嵌套在一个叫做内部的东西中并没有多大意义。或许你能提供一个更具体的例子?

【讨论】:

  • +1 - 这可能是最好的选择,假设 .inner 始终是 .outer 的直接子代,并且没有嵌套在下一层...
  • 很抱歉没有澄清这一点。这确实是一个变量。 Inner 将是后代,但不一定是直系孩子。
猜你喜欢
  • 2015-12-08
  • 2023-03-05
  • 2010-09-09
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 2015-03-30
相关资源
最近更新 更多