【问题标题】:jQuery first child of "this"“this”的jQuery第一个孩子
【发布时间】:2011-01-17 13:21:28
【问题描述】:

我正在尝试将“this”从单击的范围传递给 jQuery 函数,然后该函数可以在该单击元素的第一个子元素上执行 jQuery。好像没弄好...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

如何引用元素的 :first-child?

【问题讨论】:

  • 如果你使用 jQuery,为什么不使用 jQuery 绑定事件处理程序呢?
  • 因为绑定事件处理程序必须在 document.ready() 中初始化,这会增加性能(这是 IE6 的应用程序)。还是有其他方法?
  • 嗯..不确定。使用 jQuery 绑定是标准方式(如果您已经在使用 jQuery)。当您使用jQuery(document).ready(...) 时,您遇到了什么样的性能损失?
  • 这是一个拥有 7 个以上开发人员的大型应用程序。在我尝试清理它之前,最初是 4 多秒。所以我宁愿避免在不需要时添加更多内容:)

标签: javascript jquery jquery-selectors css-selectors


【解决方案1】:

如果您想将选择器应用于现有 jQuery 集提供的上下文,请尝试 find() function

element.find(">:first-child").toggleClass("redClass");

Jørn Schou-Rode 指出,您可能只想找到上下文元素的第一个 直接后代,因此是 the child selector (>)。 He also points out,你也可以使用 children() function,它与 find() 非常相似,但只搜索层次结构深处的一层(这就是你所需要的......):

element.children(":first").toggleClass("redClass");

【讨论】:

  • 谢谢!完美运行。我想下面列出的其他方法也可以。
  • 我相信find() 会搜索所有后代,:first-child 可以匹配每个父元素一个元素。因此,此查询可能会返回多个元素。还是我弄错了?
  • 我知道这是一个老问题/答案,但是从 jQuery 1.8 开始,在该选择器中没有父级的 ">" 选择器的使用已被弃用(例如,">:firstchild")。我建议改用element.children(":first-child")element.children().first();
  • @KevinB 显然他们决定不弃用它
  • 最好的方法不是迭代所有项目,然后选择第一个,正如一些人建议的那样。这会很糟糕。
【解决方案2】:

你试过了吗

$(":first-child", element).toggleClass("redClass");

我认为您想将元素设置为搜索的上下文。可能有更好的方法来做到这一点,其他一些 jQuery 大师会跳到这里并扔给你:)

【讨论】:

  • 如果element 有孙子,这将失败
【解决方案3】:

使用children function:first selector 来获得element单个第一个孩子:

element.children(":first").toggleClass("redClass");

【讨论】:

  • element.children()[0].toggleClass("redClass");
  • @Zakos: TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'
【解决方案4】:

我添加了jsperf 测试以查看获取第一个孩子(总共 1000 多个孩子)的不同方法的速度差异

给定,notif = $('#foo')

jQuery 方式:

  1. $(":first-child", notif) - 4,304 ops/sec - 最快
  2. notif.children(":first") - 653 ops/sec - 慢 85%
  3. notif.children()[0] - 1,416 操作/秒 - 慢 67%

原生方式:

  1. JavaScript native' ele.firstChild - 4,934,323 ops/sec(与firstChild相比,上述所有方法都慢了100%)
  2. 来自 jQery 的本机 DOM 元素:notif[0].firstChild - 4,913,658 ops/sec

因此,不推荐前 3 种 jQuery 方法,至少对于第一个孩子(我怀疑其他许多方法也是如此)。如果您有一个 jQuery 对象并且需要获取第一个子对象,则 从 jQuery 对象中获取本机 DOM 元素,使用数组引用 [0](推荐).get(0) 并使用 ele.firstChild。这给出了与常规 JavaScript 使用相同的结果。

所有测试都在 Chrome Canary 版本 v15.0.854.0 中完成

【讨论】:

  • 实际上,firstChild 不会给出与 jQuery 的 children() 或选择器查询相同的结果。 firstChild 将包含很少需要的文本节点。 jQuery 的 contents() 函数 包含它们,但 children() 不会。较新的浏览器支持firstElementChild,它将给出第一个子元素,但 IE firstChild,则必须手动查找第一个非文本节点子节点。
  • $(":first-child", notif) 应该是 $(":first", notif) 以获得预期的行为。前者将返回所有第一个子元素的后代。
【解决方案5】:

请这样使用 首先给标签 p 一个类名,比如“myp”

然后使用下面的代码

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})

【讨论】:

    【解决方案6】:

    如果你想要第一个孩子,你需要

        $(element).first();
    

    如果你想从你的元素中获得特定的第一个元素,那么在下面使用

        var spanElement = $(elementId).find(".redClass :first");
        $(spanElement).addClass("yourClassHere");
    

    试试看:http://jsfiddle.net/vgGbc/2/

    【讨论】:

    • 这是错误的 - 如果 element 是一个 DOM 节点,那么 $(element).first() 相当于 $(element),而不是它的第一个子节点。
    • 同意,如果元素是 DOM 节点 $(element).first() 是等效的 $(element) 这导致了我与 knockoutJS 绑定的问题
    【解决方案7】:

    我刚刚编写了一个插件,如果可能,它使用.firstElementChild,并在必要时回退到迭代每个单独的节点:

    (function ($) {
        var useElementChild = ('firstElementChild' in document.createElement('div'));
    
        $.fn.firstChild = function () {
            return this.map(function() {
                if (useElementChild) {
                    return this.firstElementChild;
                } else {
                    var node = this.firstChild;
                    while (node) {
                        if (node.type === 1) {
                            break;
                        }
                        node = node.nextSibling;
                    }
                    return node;
                }
            });
        };
    })(jQuery);
    

    它不如纯 DOM 解决方案快,但在 Chrome 24 下的 jsperf tests 中,它比任何其他基于 jQuery 选择器的方法快几个数量级。

    【讨论】:

    • 我喜欢这个插件 - 但有两个问题:1) 插件脚本不能包含在头部,因为 document.body 尚未初始化,2) 性能仅比替代方案好得多,如果子节点的数量非常多。对于只有几个孩子(比如少于 10 个),$('&gt;:first-child',context) 会快一点。只有孩子的数量会影响性能,而不是深度。
    • @codefactor 关于document.body 的好点子——我会调查的。
    【解决方案8】:

    这可以通过如下简单的魔法来完成:

    $(":first-child", element).toggleClass("redClass");
    

    参考:http://www.snoopcode.com/jquery/jquery-first-child-selector

    【讨论】:

      【解决方案9】:
      element.children().first();
      

      找到所有孩子并获得第一个。

      【讨论】:

      • 目前为止最简单的方法,比.children(':first')效率更高。
      • 如何更高效?似乎它获取所有孩子,然后获取第一个孩子,而不是只获取第一个孩子。
      【解决方案10】:

      你可以使用 DOM

      $(this).children().first()
      // is equivalent to
      $(this.firstChild)
      

      【讨论】:

        猜你喜欢
        • 2017-03-11
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 2013-06-06
        • 2023-03-16
        • 1970-01-01
        • 2012-02-09
        • 2019-07-23
        相关资源
        最近更新 更多