jQuery:跳过第一行表格

3
这是HTML代码:

这是HTML:

<table id="tblTestAttributes">
    <thead>
        <tr> <th>Head 1</th> <th>Head 2</th> </tr>
    </thead>
    <tbody>
        <tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
        <tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
        <tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
    </tbody>            
</table>

这是获取每行数值的JavaScript代码:

var frequencies = [];
if ($('#tblTestAttributes').length) {
    $('#tblTestAttributes tr').each(function () {
        var t = $(this).find('td[id^="txtDesc"]').text() + ";" + $(this).find('[id^="ddlFreq"] option:selected').val();
        alert(t);
        frequencies.push(t);
    });
}

我想跳过第一行,因为它只包含用于显示标题的th元素,不包含任何数据。

所以我将选择器更改为:

#tblTestAttributes tr:not(:first-child)

这里也跳过了第二个 tr,发生了什么?

2
一个ID必须是唯一的。请使用类代替。 - wakooka
已编辑HTML片段以包括thead和tbody。 - Animesh
你关于使用ID而不是类名是正确的。直到你提到它,我才注意到这一点。再次强调,在我们的项目中HTML完全由UI设计师掌控,所以我需要向他们推荐这个更改。谢谢。 - Animesh
5个回答

7
您可以使用以下简单的代码
$('#tblTestAttributes tr:not(:has(th))').each(function () {

1
在我看来,这是最优雅的解决方案。 - Sanguinary

3

使用

#tblTestAttributes tr:gt(0)

或者
#tblTestAttributes tbody tr

我建议选择第二种方法,因为它可以利用querySelectorAll,并且应该是最快的解决方案。
你的方法没有按预期工作,因为第二个tr也是tbody的第一个子元素。

3

从性能方面考虑,使用.find()比使用Sizzle解析选择器更好。

$('#tblTestAttributes').find('tbody').find('tr').each(function () { ... });

这里是展示它的 jsPerf


谢谢您向我展示链接的用法。在我采纳答案之前,我没有看到您的回答。 - Animesh
你能解释一下在这个上下文中 sizzle 是什么吗?我问这个问题是因为我只是在三周前开始学习 jQuery,并且是边学边做。 - Animesh
当你写$(...).someFunction()时,你正在向函数传递一些元素。要获取这些元素,你可以使用内部的sizzle引擎(这就是其他答案所做的)或者你可以使用$('#elementID')获取顶层元素,因为它是一个ID,所以没有什么需要解决的问题,然后使用.find()来过滤你需要的内容,在这种情况下是第一行但不包括标题。你应该更改接受的答案。 - frenchie
如果你只是在为桌面端工作,那么性能可能并不重要,但对于移动端来说,你应该考虑性能。此外,如果你保持使用sizzle选择器的习惯,最终会有一些非常复杂的选择器,这可能会导致页面卡顿,特别是如果涉及到ajax。 - frenchie
感谢您抽出时间解释什么是Sizzle。 - Animesh
1
没问题。事实上,我刚刚意识到你的内部函数也在使用sizzle。假设你已经将HTML更正为在行中使用类而不是ID,那么我会这样重写它们:var t = $(this).find('.txtDesc').text() + ";" + $(this).find('.ddlFreq').val(); 另外,如果你正在使用.each()循环,并且在循环内部频繁使用$(this),那么循环的第一行应该是var This = $(this);以缓存$(this)的值,然后你可以使用var t = This.find... 在这里,你只使用了$(this)两次,所以没有必要缓存它,但请记住这一点。 - frenchie

2
使用tr + tr选择器,它获取所有在另一个tr之后出现的tr,因此第一个被跳过。
此外,无需检查表是否存在,因为在这种情况下,$.each甚至不会被执行。
var frequencies = [];
    $('#tblTestAttributes tr + tr').each(function () {
        var t = $(this).find('td[id^="txtDesc"]').text() + ";" + $(this).find('[id^="ddlFreq"] option:selected').val();
        alert(t);
        frequencies.push(t);
    });

编辑后:

只需选择 tbody 内的所有 tr 即可:

$('#tblTestAttributes tbody tr').each(function(){
    ...
}

您改变了HTML,现在这完全是另一个问题 :)。 - XCS
嘿,对不起。我以为我正在操作TRs,所以thead和tbody不重要,但后来觉得我应该让问题更清楚。 - Animesh
1
这是一个较慢的选项:http://jsperf.com/find-vs-sizzle-for-table-row-loop。查看我的答案以获取更好的性能。 - frenchie
1
除非你在处理数十万个元素/操作,否则JavaScript中不存在“慢”的情况,我真的很怀疑这种情况是否存在 :)。 - XCS
1
@frenchie:如果性能真的是一个问题,那么第一件要做的事情就是放弃jQuery并使用本地代码。http://jsperf.com/find-vs-sizzle-for-table-row-loop/2 与您和Cristy的答案相比,它们的性能非常相似。而与本地代码相比,差距是巨大的。 - user2437417
哇,确实如此。我只是想优化选择器,但确实,使用本地代码比使用jQuery要快得多。 - frenchie

1
这是因为第二行实际上是的第一个子元素,就像第一行是的第一个子元素一样。
为了仅获取您所需的元素,我建议使用更接近您需要的内容的方法:
#tblTestAttributes tr:has(td)

不要忘记去掉那些重复的txtDesc id,这在HTML中是非法的,请使用class代替。


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