【问题标题】:jQuery: skipping first table rowjQuery:跳过第一行
【发布时间】:2013-07-27 21:35:53
【问题描述】:

这是 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。这里发生了什么?

【问题讨论】:

  • ID 必须是唯一的。改用类。
  • 已编辑以在 HTML sn-p 中包含 thead 和 tbody。
  • 使用 ID 而不是类是正确的。直到你提到我才注意到。 HTML(在我们的项目中)再次完全掌握在 UI 设计师手中,所以我需要将此更改推送给他们。谢谢。

标签: javascript jquery


【解决方案1】:

简单的你可以使用下面的代码

$('#tblTestAttributes tr:not(:has(th))').each(function () {

【讨论】:

  • 这是我认为最优雅的解决方案。
【解决方案2】:

在性能方面,使用.find()会比使用Sizzle解析选择器要好。

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

这里是 jsPerf 来展示它。

【讨论】:

  • 感谢您向我展示链接。在我接受答案之前,我没有看到您的答案。
  • 你能解释一下在这种情况下什么是嘶嘶声吗?我问这个问题是因为我三周以来才跳入 jQuery 的海洋,并且边走边学。
  • 当您编写 $(...).someFunction() 时,您将一些元素传递给函数。要获取元素,您可以使用内部嘶嘶声引擎(这是其他答案所做的),或者您可以使用 $('#elementID') 获取顶级元素,因为它是一个 ID,所以没有什么需要解决的,然后使用 .find() 过滤您需要的内容,在这种情况下是第一行而不是标题。您应该更改接受的答案。
  • 如果您只为桌面工作,那么性能可能并不重要,但对于移动设备,您应该考虑性能。此外,如果您保持使用 sizzle 选择器的习惯,您最终会遇到一些非常复杂的选择器,这些选择器会导致页面停止运行,尤其是在涉及 ajax 的情况下。
  • 没问题。其实刚刚意识到你的内部函数也在使用sizzle。这就是我重写这些的方式,假设您已将 HTML 更正为在行中使用类而不是 ID: var t = $(this).find('.txtDesc').text() + ";" + $(this).find('.ddlFreq').val();另外,如果你使用 .each() 循环并且你在循环中做了很多 $(this) 那么循环的第一行应该是 var This = $(this);缓存 $(this) 的值,然后你会使用 var t = This.find... 这里你只使用了两次 $(this) 所以没有必要缓存它,但请记住这一点。
【解决方案3】:

使用

#tblTestAttributes tr:gt(0)

#tblTestAttributes tbody tr

我会推荐第二个,因为它可以利用 querySelectorAll 并且应该是最快的解决方案。

您的方法没有按预期工作,因为第二个tr 也是first-child(tbody)

【讨论】:

    【解决方案4】:

    使用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);
        });
    

    修改后:

    只选择tr 内的所有tbody

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

    【讨论】:

    • 你改变了html,现在这是一个完全不同的问题:)。
    • 嘿,对不起。我的印象是我在 TRs 上操作,所以 thead 和 tbody 应该无关紧要,但后来觉得我应该更清楚地说明问题。
    • 这是一个缓慢的选项:jsperf.com/find-vs-sizzle-for-table-row-loop 看看我对性能的回答。
    • 除非您谈论成百上千的元素/操作,否则 javascript 中没有“慢”,我真的怀疑是这种情况:)。
    • @frenchie:如果性能确实是个问题,那么首先要做的就是放弃 jQuery 并转为原生。 jsperf.com/find-vs-sizzle-for-table-row-loop/2 相比之下,您的答案和 Cristy 的答案非常相似。你和本地人的区别是巨大的
    【解决方案5】:

    这是因为第二行实际上是tbody 的第一个孩子,就像第一行是thead 的第一个孩子一样。

    只取你需要的元素,我建议你的需要更接近:

    #tblTestAttributes tr:has(td)
    

    不要忘记删除那些重复的txtDesc id,这在 HTML 中是非法的,请改用类。

    【讨论】:

      猜你喜欢
      • 2012-02-03
      • 2012-08-31
      • 2014-06-07
      • 2013-08-17
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      相关资源
      最近更新 更多