jQuery "this" 的第一个子元素

355
我试图从被点击的span中传递"this"到一个jQuery函数,然后对该点击元素的第一个子元素执行jQuery操作。似乎做不对...
<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

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

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


4
如果你正在使用jQuery,为什么不也使用jQuery来绑定事件处理程序? - Vivin Paliath
2
因为绑定事件处理程序必须在document.ready()中初始化,这会增加性能开销(这是一个针对IE6的应用程序)。还有其他方法吗? - macca1
嗯...不太确定。如果您已经在使用jQuery,那么使用jQuery进行绑定是标准方式。当您使用jQuery(document).ready(...)时,您会遇到什么样的性能问题? - Vivin Paliath
这是一个由7个以上开发人员构建的大型应用程序。在我尝试对其进行一些清理之前,它原本需要4秒以上才能运行。因此,如果不必要,我宁愿避免再添加更多内容 :) - macca1
11个回答

534

如果你想将选择器应用于现有 jQuery 集合所提供的上下文中,请尝试使用 find() 函数

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

Jørn Schou-Rode指出,您可能只想要找到上下文元素的第一个直接后代,因此要使用子选择器(>)他还指出,也可以使用children()函数,它与find()非常相似,但仅在层次结构中搜索一级深度(这正是您所需要的...):

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

1
谢谢!运行得非常完美。我想下面列出的其他方法也会起作用。 - macca1
6
我认为 find() 方法会在所有后代元素中搜索,而 :first-child 选择器每个父元素只匹配一个子元素。因此,这个查询很可能会返回多个元素。或者我错了吗? - Jørn Schou-Rode
@Jørn:你说得对,我没有考虑到这个问题 - 如果存在层级关系,那么一个未经限定的:first-child选择器会产生多个结果。 - Shog9
21
我知道这是一个旧的问题/答案,但在 jQuery 1.8 中,使用带有无父级的 ">" 选择器(例如,">:firstchild")的方法已被弃用。我建议改用 element.children(":first-child")element.children().first();。请注意不要改变原意。 - Kevin B
3
@KevinB 显然他们最终决定不废弃它。 - Alnitak
1
最好的方法不是遍历所有项目,然后选择第一个,就像一些人在这里建议的那样。这将是不好的。 - vsync

88

element.children()[0].toggleClass("redClass"); - Zakos
7
@Zakos: TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass' 的翻译是:类型错误:对象[object HTMLAnchorElement]没有'toggleClass'方法。 - Jørn Schou-Rode

61

我已经添加了jsperf测试,以查看获取第一个子级(总计1000多个子级)的不同方法之间的速度差异。

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

jQuery方法:

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

本地方法:

  1. JavaScript 原生的 ele.firstChild - 每秒 4,934,323 次操作(与上述所有方法相比,速度提高了 100%)
  2. 从 jQuery 获取本地 DOM 元素:notif[0].firstChild - 每秒 4,913,658 次操作

因此,前三种 jQuery 方法不建议使用,至少对于第一个子级(我怀疑这也会是许多其他子级的情况)。如果你有一个 jQuery 对象并需要获取第一个子级,则使用数组引用[0](推荐).get(0)从 jQuery 对象中获取本地 DOM 元素,并使用ele.firstChild。这与常规 JavaScript 用法完全相同。

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


24
实际上, firstChild 的结果与 jQuery 的 children() 或选择器查询并不相同。 firstChild 将包括文本节点,这很少是需要的。 jQuery 的 contents() 函数会*包括它们,但是 children() 不会。 新版浏览器支持 firstElementChild ,它将提供第一个子元素,但 IE < 9不支持它。 因此,如果您使用 firstChild ,则必须手动查找第一个非文本节点子元素。 - Max
3
为了实现预期的行为,$(":first-child", notif) 应该改为 $(":first", notif)。前者会返回所有第一个子元素后代。 - Drazen Bjelovuk
当没有文本节点作为直接子元素时,您可以选择使用$(notif[0].firstChild)以提高性能,特别是在涉及许多子元素时。然后,您将再次得到一个jQuery对象。在JSBench.me上,我使用了1000个子节点进行测试,使用notif.children(":first")获得了8,728个操作/秒,而使用$(notif[0].firstChild)则获得了惊人的12,440,220个操作/秒。 - Piemol

32
element.children().first();

查找所有的子元素并获取第一个子元素。


3
目前最简单的方法,比.children(':first')更高效。 - Gras Double
5
它为什么更有效率?看起来它获取了所有子元素,然后取第一个,相比只获取第一个子元素。 - Anthony McGrath
2
@AnthonyMcGrath https://dev59.com/rXE95IYBdhLWcg3wbtbO#14757072 - Wtower

13

你可以使用DOM

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

10

你试过了吗

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

我认为你想将你的元素设置为搜索的上下文。可能还有一种更好的方法,其他jQuery大师会在这里跳进来为你提供解决方法 :)


3
如果element有孙子节点,这将失败。 - Alnitak

5

我刚写了一个插件,它尽可能使用.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测试中,它比任何其他基于jQuery选择器的方法都要快几个数量级。


1
我喜欢这个插件 - 但有两个问题:1)插件脚本不能包含在头部,因为 document.body 尚未初始化,2)仅当子节点数量非常高时,性能才比替代方案好得多。对于只有少数儿童(比如少于10个),$(' >:first-child',context) 稍微快一点。只有儿童的数量影响性能,而不是深度。 - codefactor
@codefactor 提到了 document.body 的好处,我会研究一下。 - Alnitak

4

请按照以下方式使用

首先,给标签P以“myp”类名

然后使用以下代码

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

3
这可以通过如下简单的魔法实现:
$(":first-child", element).toggleClass("redClass");

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

该网页介绍了jQuery中的:first-child选择器,它可以选择作为其父元素的第一个子元素的元素。 该选择器可以用于在网页上查找特定元素并对其进行操作,从而使开发人员更轻松地控制网页的外观和行为。

-2

我正在使用

 $('.txt').first().css('display', 'none');

这是完全错误的吗?除了脚本中没有定义txt类之外,first()也无法完成任务:“给定一个代表一组DOM元素的jQuery对象,.first()方法从该集合中的第一个元素构造一个新的jQuery对象。” [链接](https://api.jquery.com/first/) - fseydel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接