jQuery:.has()和:has()之间的细微差别

时间:2010-10-15 18:08:51

标签: jquery sizzle

当与子选择器>一起使用时,jQuery的“has”的两个变体表现不同。

拿这个HTML:

<div>
  <span>Text</span>
</div>

现在:

$("div:has(>span)");

将返回它,而:

$("div").has(">span");

不会。这是一个错误还是一个功能?比较一下:http://jsfiddle.net/aC9dP/


编辑:这可能是一个错误或至少是无证件的不一致行为。

无论如何,我认为让子选择器始终作为一元运算符是有益的。它使您能够执行其他需要自定义过滤功能的操作 - 它允许您直接选择具有特定子项的元素:

$("ul:has(>li.active)").show();     // works
$("ul").has(">li.active)").show();  // doesn't work, but IMHO it should

而不是:

$("ul").filter(function () {
  return $(this).children("li.active").length > 0;
}).show();

我为此打开了a jQuery ticket (7205)

2 个答案:

答案 0 :(得分:7)

这是因为sizzle选择器正在查看所有具有跨越子项的Div:示例。但是在.has示例中,它将所有DIV传递给.has(),然后查找不应该是独立选择的东西。 (“没有孩子”)。

基本上,:has()是选择的一部分,但.has()会传递这些div,然后从中重新选择。

理想情况下,您不要使用这样的选择器。 &gt;在选择器中可能是一个错误,因为它在语义上很尴尬。注意:子操作符并不是独立的。

Sizzle vs target.sizzle:

我一直在谈论v1.4.2 of jquery development release

.has (jQuery第3748行)

描述:将匹配元素集减少为具有与选择器或DOM元素匹配的后代

代码:

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

第3642行涉及2008插件compareDocumentPosition,但重要的是我们现在基本上只在这里运行两个jquery查询,其中第一个选择$("DIV")而下一个选择$(">span")(返回null),然后检查子项。

(jQuery第3129行)

描述:选择元素,其中包含至少一个与指定选择器匹配的元素

代码:

return !!Sizzle( match[3], elem ).length;

它们是两个不同的工具,:使用100%的嘶嘶声,而且。使用传递给它的目标。

注意:如果您认为这是一个错误,请填写错误提示。

答案 1 :(得分:1)

我想你可能遇到了一个真正的错误。问题可能在于您使用子选择器的方式。正如user257493指出的那样,它并不意味着单独使用(或者至少我在文档中没有看到任何这样的例子。

虽然检查了这一点。如果您在*中的子选择器之前添加.has(),那么它会突然起作用:http://jsfiddle.net/Ender/FjgZn/

但如果你在:has()选择器中做同样的事情,它就会停止工作!看这里: http://jsfiddle.net/Ender/FjgZn/

这两者的实施方式肯定存在差异。