代码之家  ›  专栏  ›  技术社区  ›  Tomalak

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

  •  10
  • Tomalak  · 技术社区  · 14 年前

    与子选择器一起使用时 > ,jquery的“has”的两个变体的行为不同。

    使用这个HTML:

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

    现在:

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

    将其退回,同时:

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

    不会。它是一个bug还是一个特性?比较这里: 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 回复  |  直到 14 年前
        1
  •  7
  •   Incognito    14 年前

    之所以会发生这种情况,是因为sizzle选择器正在查看:has示例中具有SPAN子级的所有DIV。但是在.has示例中,它将所有的div传递给.has(),然后它将查找不应该是独立选择的内容。(没有孩子)。

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

    理想情况下,您不使用这样的选择器。在选择器中的>可能是一个bug,因为它在语义上很尴尬。注意:儿童操作员不应该是独立的。

    sizzle与target.sizzle:

    我一直在说 v1.4.2 of jquery development release .

    (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") (返回空值),然后检查子级。

    (jquery第3129行)

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

    代码:

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

    它们是两种不同的工具:has使用sizzle 100%,has使用传递给它的目标。

    注意:如果你认为这是一个错误,去填写错误通知单。

        2
  •  1
  •   Ender    14 年前

    我想你可能碰到了一个真正的虫子。问题可能在于您使用子选择器的方式。正如用户257493所指出的,它并不打算单独使用(或者至少我在文档中没有看到任何这样的例子)。

    不过,看看这个。如果添加 * 在子选择器之前 .has() 突然,它开始工作: http://jsfiddle.net/Ender/FjgZn/

    但如果你在 :has() 选择器,它停止工作!请参见这里: http://jsfiddle.net/ender/fjgzn/

    这两种方法的实现方式显然存在差异。