【问题标题】:Difference in results returned between .has() and :has().has() 和 :has() 之间返回的结果差异
【发布时间】:2010-10-20 04:59:31
【问题描述】:

我有一个粗糙的导航结构,可以概括为:

<ul id="navigation">
    <li>
        A
        <ul>
            <li>
                B
                <ul>
                    <li>C</li>
                </ul>
            </li>
            <li>
                D
                <ul>
                    <li>
                        E
                        <ul>
                            <li>F</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

子项在悬停之前一直隐藏。我想通过样式来表明 B、D 和 E 有子项,所以我使用了选择器:

$('#navigation > li li:has(ul)')

仅返回 B 和 D。将其更改为:

$('#navigation > li li').has('ul')

退回了所有正确的物品,但我不知道为什么。

编辑

:has() 似乎(完全)不受嵌套的影响

$('#navigation ul > li:has(ul)')

返回与上述.has() 相同的结果。

【问题讨论】:

  • 在我看来结果应该是一样的。我不知道他们为什么不一样。当找到匹配项时,也许 Sizzle 会放弃查找嵌套元素。如果是这样,这似乎忽略了相同嵌套元素的可能性(就像您在示例中所看到的那样)。

标签: jquery


【解决方案1】:

来自 jQuery API 文档:

:has 选择的元素 至少包含一种元素 匹配指定的选择器。

.has() 减少集合 匹配元素到那些有 匹配选择器的后代 或 DOM 元素。

这里有一个相关的问题:jQuery: subtle difference between .has() and :has(),这似乎表明了两者的区别。

但是,:has 似乎不会以嵌套方式在匹配中查找,而 .has() 这样做是因为它返回匹配的子集,因为 jQuery 对象能够匹配所有后代,甚至是嵌套的后代,就像一个普通的 jQuery 选择器。

【讨论】:

  • 这些是从文档herehere 复制的描述。它如何使它们与众不同?在我看来,它们应该返回相同的结果。
  • 您发布的链接特定于选择器以 &gt; 开头的问题。
  • 我必须同意@patrick - 这根本不能回答问题,:has() 描述意味着它应该找到第三个元素E。另外,您应该想知道这些描述的来源。
  • 我认为该链接为我们提供了一个线索,即无论子选择器的具体用途如何,都会发生什么
  • @Moin - 不是真的。在那个问题中情况正好相反。在那里,:has() 选择器版本有效,而.has() 方法无效。事实上,该方法返回0 结果。不同的问题。
【解决方案2】:

:has() selector 仅选择那些具有与给定选择器匹配的降序元素的元素。在内部,:has is defined 为(Sizzle 是 jQuery 默认选择器库):

function(elem, i, match){
    return !!Sizzle( match[3], elem ).length;
}

这几乎等同于为每个选定元素测试 jQuery("selector", elem).lengthjQuery(elem).find("selector").length 以过滤那些没有此类后代的元素。

与此相反,has method 可以采用选择器或 DOM 元素,并且只返回那些不包含任何给定元素的元素。因为在内部,has method is defined 为:

function( target ) {
    var targets = jQuery( target );
    return this.filter(function() {
        for ( var i = 0, l = targets.length; i < l; i++ ) {
            if ( jQuery.contains( this, targets[i] ) ) {
                return true;
            }
        }
    });
}

因此它使用contains method 来检查是否包含给定元素以过滤所选元素。请注意,只包含一个给定元素就足够了。

【讨论】:

  • 但这并不能解释行为,这是 Sizzle 中的一个错误,因为它应该返回这些元素,问题是选择器部分的数组在此弹出错误设想。例如:$('#navigation li li:has(ul)') 将给出 3 个元素。
猜你喜欢
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
相关资源
最近更新 更多