使用时:children()和find()的行为:首先

时间:2014-08-14 11:26:18

标签: jquery

我对children()find()使用:first时的行为感到有点困惑。

考虑以下标记:

<div class="parent">
    <div>1</div>
    <div class="child">2</div>
    <div class="child">3</div>
</div>

<div class="parent">
    <div>1</div>
    <div class="child">2</div>
    <div class="child">3</div>
</div>

根据我的理解,以下内容应返回相同的元素集合,因为没有孙子(这是documentationfind()children()之间唯一的差异)

但是,如果我向第一个.child添加一个类,则结果会有所不同:

$('.parent').find('.child:first').addClass('active');

以下标记中的结果:

<div class="parent">
    <div>1</div>
    <div class="child active">2</div>
    <div class="child">3</div>
</div>

<div class="parent">
    <div>1</div>
    <div class="child active">2</div>
    <div class="child">3</div>
</div>

当使用children()方法做同样的事情时,我得到:

<div class="parent">
    <div>1</div>
    <div class="child active">2</div>
    <div class="child">3</div>
</div>

<div class="parent">
    <div>1</div>
    <div class="child">2</div>
    <div class="child">3</div>
</div>

为什么?

Here's a fiddle

3 个答案:

答案 0 :(得分:3)

好问题!

TL; DR

区别在于find从每个包装元素开始单独搜索,然后聚合结果,而children获得候选结果的单个聚合池,然后根据指定的选择器进行过滤。如果原始jQuery对象包含多个元素,这会导致像:first这样的选择器给出不同的结果。

原因是可以理解的(children从一开始就知道所有可能的匹配在DOM中共享一个非常重要的属性,所以有必要预先缩小候选列表的性能原因),但IMO你不能将结果调用为当前实现中的错误。

$.fn.find

find产生两个匹配,因为它在当前jQuery对象的每个包装元素上运行搜索,然后聚合结果。因此,对于每个.parent,我们匹配文档顺序为.child的第一个后代。

这是来源:

function (selector) {
    var i, ret = [],
        self = this,
        len = self.length;

    if (typeof selector !== "string") {
        return this.pushStack(jQuery(selector).filter(function () {
            for (i = 0; i < len; i++) {
                if (jQuery.contains(self[i], this)) {
                    return true;
                }
            }
        }));
    }

    for (i = 0; i < len; i++) {
        jQuery.find(selector, self[i], ret);   // ** IMPORTANT **
    }

    // Needed because $( selector, context ) becomes $( context ).find(selector)
    ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret);
    ret.selector = this.selector ? this.selector + " " + selector : selector;
    return ret;
}

所有内容都发生在标有“重要”的行中:jQuery.findSizzle的别名,每次都将的结果附加到ret。显然,如果你对包含N个元素的jQuery对象进行.find(":first"),每个元素至少有一个后代,那么你将获得N个结果。

$.fn.children

children采用另一种方式:对于每个包装元素,它遍历DOM以获取其子项,然后根据选择器过滤结果作为整体。显然,在这种情况下,这最多会留下一个元素作为最终结果。

以下是它的发生方式:

function (until, selector) {
    var ret = jQuery.map(this, fn, until); // ** IMPORTANT 1 **

    if (name.slice(-5) !== "Until") {
        selector = until;
    }

    if (selector && typeof selector === "string") {
        ret = jQuery.filter(selector, ret); // ** IMPORTANT 2 **
    }

    if (this.length > 1) {
        // Remove duplicates
        if (!guaranteedUnique[name]) {
            ret = jQuery.unique(ret);
        }

        // Reverse order for parents* and prev-derivatives
        if (rparentsprev.test(name)) {
            ret = ret.reverse();
        }
    }

    return this.pushStack(ret);
}

这不是不言自明的,因为代码与一堆对DOM进行结构遍历的方法共享(parentnextprev,{{1} }等等,但代码的相关部分也非常简单:“重要1”行收集siblings内部结构遍历(“获取子项”)的结果,这些结果作为一个整体根据选择器(ret)进行过滤。这最终会留下一个结果。

答案 1 :(得分:-1)

    The children() method returns all direct children of the selected element.
    The find() method returns descendant elements of the selected element.
please check below links for that

http://www.w3schools.com/jquery/traversing_find.asp
http://www.w3schools.com/jquery/traversing_children.asp

答案 2 :(得分:-2)

来自Jquery API

The .children() method differs from .find() in that .children() only travels a single level down the DOM tree while .find() can traverse down multiple levels to select descendant elements (grandchildren, etc.) as well.

这可以解释为什么.children()只在.find()通过所有内容时将活动类放在其中一个上