【问题标题】:jQuery "hasParent"jQuery“有父母”
【发布时间】:2011-01-24 06:37:42
【问题描述】:

JQuery 的“has”方法有效地选择了它们具有特定后代的所有元素。

我想根据元素具有特定祖先的事实来选择元素。我知道 parent([selector]) 和 parents([selector]) 但这些选择父母而不是父母的孩子。

那么有没有相当于“有”的祖先?

注意:我已经有了一个元素的上下文,在层次结构的下方,我将基于此进行选择,因此我无法进行“自上而下”的查询。

更新

我显然在这里解释得很糟糕,所以我会试着澄清一下:

<ul class="x">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
<ul class="y">
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

我有一个已包含元素 2、3、4 和 5 的 jQuery 对象。我想选择那些父元素为 class= x 的元素。

希望这更有意义。

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    对于一个干净的可重用解决方案,请考虑使用自定义方法扩展 jQuery.fn 对象,该方法用于确定任何给定元素的特定祖先是否存在:

    // Extend jQuery.fn with our new method
    jQuery.extend( jQuery.fn, {
        // Name of our method & one argument (the parent selector)
        within: function( pSelector ) {
            // Returns a subset of items using jQuery.filter
            return this.filter(function(){
                // Return truthy/falsey based on presence in parent
                return $(this).closest( pSelector ).length;
            });
        }
    });
    

    这产生了一个新方法$.fn.within,我们可以使用它来过滤我们的结果:

    $("li").within(".x").css("background", "red");
    

    这会选择文档上的所有列表项,然后过滤到仅以.x 作为祖先的那些项。因为这在内部使用了 jQuery,所以你可以传入一个更复杂的选择器:

    $("li").within(".x, .y").css("background", "red");
    

    这会将集合过滤到来自.x.y 或两者的项目。

    小提琴:http://jsfiddle.net/jonathansampson/6GMN5/

    【讨论】:

    • 这是我试图避免的“自上而下”的方法,因为我已经有了想要开始的元素。这就是我在上一篇笔记中试图解释的内容。假设您已经在 jquery 变量中的该列表中拥有第二个和第三个跨度,您如何进一步过滤该列表?
    • 如果我理解正确,克里斯,我的待更新解决了这个问题。
    • 我对过滤方法不太熟悉。根据我的编辑,您仍然认为这样做可以吗?
    • @Chris Simpson:从你的编辑(和乔纳森的)来看,我不得不说是的。假设您将.parent 替换为.x
    • 使用return !!$(p).find(this).length; 实际返回truefalse
    【解决方案2】:

    if ( $('.foo').parents('.parentSelector').length ) { // has parent }

    【讨论】:

    • 这仅适用于单个元素。我想选择所有父母符合特定条件的孩子。但我已经有一个 jquery 对象可供选择,它位于层次结构的较低位置(如果这有意义的话)
    • 为什么这只适用于单个元素?如果你的选择器是正确的,你应该没问题。我上面的代码读取“对于具有类 'foo' 的 所有 元素,找到具有类 'parentSelector' 的父元素并返回该 jQuery 集合”。也许我遗漏了什么……举个例子?
    • 你在说“如果我的元素有一个匹配的父元素,做点什么”。我想说“基于这个元素列表,给我一个父元素匹配特定条件的元素列表”
    • +1 我最喜欢这个解决方案。不过,jQuery 确实应该将 hasParent() 添加到他们的 API 中。
    【解决方案3】:

    如果我正确理解您的问题,可以这样做:

    $.fn.hasAncestor = function(a) {
        return this.filter(function() {
            return !!$(this).closest(a).length;
        });
    };
    
    $('.element').hasAncestor('.container').myAction();
    
    <div class="container">
      <span>
        <strong class="element">strong</strong>
      </span>
    </div>
    

    【讨论】:

    • 因为这个值过滤了父母,而不是返回真/假,我建议将其重命名为withAncestorfilterAncestor。如果我正在阅读代码,我希望 hasAncestor 返回一个布尔值
    • ...虽然我可能会收回这一点,因为 jQuery 核心有一个“has()”,它的行为相同,但对于后代。 api.jquery.com/has
    • 另一方面,hasClass() 返回一个布尔值...让我想起了 two hard things in computer science...
    • 严格来说,这个实现是不正确的,因为closest()也会匹配当前选中的元素。也就是说,$('.element').hasAncestor('.element'); 将始终返回自身。您传递给filter 的函数应该返回!!$(this).parent().closest(a).length
    【解决方案4】:
    $('body').hasParent('html') //true
    
    $('div#myDiv').hasParent($('body')) //true
    

    #API:

    // check if current element has parent element 'e' 
    $.fn.hasParent = function (e) {
        return !!$(this).parents(e).length
    }
    

    【讨论】:

    • 或者至少应该是双感叹号“!!”将结果转换为布尔值。
    • @OytunTez : 哲学与以下 JS 规则有关:- “0”在逻辑谓词中被认为是“假”。
    • 我的意思是,这个 return 语句是否正在反转结果(可能是在尝试将 int 转换为 boolean 时)
    【解决方案5】:

    你实际上可以直接使用filter(没有调用closest的函数),它会有更好的性能。只需使用匹配 .x 中包含的元素的选择器:

    $("li").filter(".x *")
    

    这也与其他人建议的closest 解决方案略有不同,因为如果元素本身具有给定的类,但只有当它具有该类的元素时才会匹配。

    如果还需要将元素与类匹配,则可以稍作修改:

    $("li").filter(".x, .x *")
    

    $("li").filter(".x *").css("background", "red");
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <ul class="x"><li>1</li><li>2</li><li>3</li></ul>
    <ul class="y"><li>4</li><li>5</li><li>6</li></ul>

    【讨论】:

      【解决方案6】:

      试试这个

      ul.myList > li > a
      

      这个选择器只选择列表元素的直接子元素的链接,它们是 反过来,具有 myList 类的元素的直接子元素。

      【讨论】:

        【解决方案7】:
        object.each(function(){
            element = $(this);
            if(element.parent().hasClass("x")){
                //do stuff
            }
        });
        

        这将影响对象中具有父 .x 的每个项目

        【讨论】:

          【解决方案8】:

          简单的方法是这样的:

          // all children of a specific parent match
          $('parentSelector').children();
          
          // All children matching a specific pattern, one level deep
          $('parentSelector > childSelector');
          // or
          // $('parentSelector').children('childSelector');
          
          // All children matching a specific pattern, multiple levels deep
          $('parentSelector childSelector');
          // or
          // $('parentSelector').find('childSelector');
          

          或者你真的需要比这更复杂的东西吗?

          编辑:如果你已经有一个元素,你可以将它与 parent() 命令结合起来,如下所示:

          myElement.parents('parentSelector').find('childSelector'); // Will include self
          

          【讨论】:

          • 在问题中添加了示例 html,可以更好地解释问题
          【解决方案9】:

          我意识到这是一个老问题,但我将这里留给未来寻找类似问题的访问者;

          有一个$.contains(container, contained) 方法返回一个布尔值。

          https://api.jquery.com/jQuery.contains/

          【讨论】:

            【解决方案10】:

            非常简单的方法

            $('.x').find('li')
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-05-15
              • 2011-01-23
              • 2011-03-30
              • 1970-01-01
              • 2019-07-23
              • 1970-01-01
              • 1970-01-01
              • 2011-08-31
              相关资源
              最近更新 更多