【问题标题】:Is there a method in jQuery that will traverse up the dom tree from an element and check selectors before its parent elementjQuery中是否有一种方法可以从元素向上遍历dom树并在其父元素之前检查选择器
【发布时间】:2012-11-15 01:01:48
【问题描述】:

例如:

<div class="mainWrapper">
    <div class="FirstLayer">
        <input class="foo" value="foo" />
    </div>

    <div class="SecondLayer">
        <div class="thirdLayer">
            <input class="fee" />
        </div>
    </div>
</div>

假设我将 input.fee 作为 jQuery 对象,我还需要获取 input.foo 的值。 现在我知道我可以使用多种方法,例如$(this).parents(':eq(2)').find('.foo'),但我想在具有不同级别和节点数量的布局上使用这种方法。 所以我想知道是否有一种方法可以简单地从.fee 开始,然后一直向上直到找到第一个匹配元素,.prevAll() 似乎没有这样做。有很多 .foo.fee 元素,我特别需要在上下文中高于 .fee 的第一个元素。

【问题讨论】:

  • 您能否展示一个包含多个 foofee 字段的示例,因为遍历很可能会有所不同
  • 你可以使用closest方法,$(this).closest('.mainWrapper').find('.foo')
  • 上升永远不会到达foo,因为它不是fee的祖先。它是fee的祖先的兄弟
  • @Asad 所以没有一个函数可以简单地在 dom 树上检查一个类的所有元素,无论是否是祖先?
  • @LaserBeak 对。它被称为树是有原因的——你不能向上遍历并期望到达一棵树的所有分支叶子

标签: javascript jquery


【解决方案1】:

这个怎么样:

$('input.fee').closest(':has("input.foo")')
              .find('input.foo').val();

这是JS Fiddle 玩。 )

更新:感谢@VisioN - 当然,parents:first 很好地被closest 取代。

【讨论】:

  • 最好使用closest() 方法,而不是应用:first 选择器。
  • @VisioN 但当然可以。 ) 被 :has 选择器弄糊涂了。
  • 太好了,我被卡住了,因为没有想到:has,而是我错误地尝试使用.closest('* input.foo') +1 以获得良好的答案:-)
  • 这不会选择带有 input.foo 的前一个 div。看看小提琴here。我认为它可能会遍历父级,但是当将它们与选择器匹配时,它必须从索引为 0 的父级开始。
  • @Bruno 是的,IMO 对此的最佳解决方案将有资格使用新的 jquery 方法,可以称为 .nearest() ,它将遍历返回执行 .prev() 检查选择器并且没有更多 prev() 它转到 parent() 并再次继续执行 prev()。
【解决方案2】:

这将选择之前的 input.foo

// self might have siblings that are input.foo so include in selection
$( $("input.fee").parentsUntil(":has(input.foo)").andSelf()

        // if input.off is sibling of input.fee then nothing will
        // be returned from parentsUntil. This is the only time input.fee
        // will be selected by last(). Reverse makes sure self is at index 0
        .get().reverse() )

        // last => closest element
        .last()                 

        //fetch siblings that contain or are input.foo elements
        .prevAll(":has(input.foo), input.foo") 

        // first is closest
        .first() 

        // return jQuery object with all descendants
        .find("*")         

        // include Self in case it is an input.foo element 
        .andSelf() 

        .filter("input.foo")

        // return value of first matching element
        .val() 

【讨论】:

  • 如果在 .firstlayer 和 .secondlayer 之间有一个元素,这将不起作用,请参阅jsfiddle.net/YZ6vg/7 在这种情况下它也不起作用jsfiddle.net/YZ6vg/8
  • 这个答案实际上和公认的答案一样好,只是每个答案都比另一个更好地处理不同的布局角落案例,但是对于任何两个答案,布局都可以很容易地完成,因此它们会失败。我重复查找 nearest 元素的一般解决方案是创建一个新的 jquery 方法,该方法将 prev() 与 parent() 结合起来,如我对已接受答案的评论中所述。
  • 哇,你的上一个版本做得很好,到目前为止它通过了所有的小提琴,但我仍然发现它失败了jsfiddle.net/YZ6vg/16
  • @Nelson 我知道我不会再得到任何分数 :) 但有机会检查上述工作。如果工作量太大,请不要打扰,只是出于兴趣。
  • 是的,您的最终版本适用于迄今为止发布的所有小提琴,恭喜:-)
【解决方案3】:

jQuery.closest() 采用选择器并完全满足您的需求 - 找到第一个匹配元素,它是某物的父元素。还有jQuery.parents() 确实使用选择器来过滤元素祖先。将这些与find 方法结合使用即可。

$('input.fee').closest('.mainWrapper").find('.foo') 成功了,不是吗?

【讨论】:

  • 不幸的是,这并不是他真正需要的。
  • 但是foo 不是fee 的父级,它是父级的子级。
  • 没有对你投反对票,但closest 应该在这里只与:has 组合使用 - 它遍历 DOM 树,但不会向下看每一步。 )
猜你喜欢
  • 1970-01-01
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 2012-05-12
  • 2014-09-30
  • 1970-01-01
  • 2014-10-15
相关资源
最近更新 更多