jQuery显示/隐藏大表格列性能问题

7

我有一个包含大约30列和10到500行的HTML表格。我希望在按钮点击时显示/隐藏一组列。

我尝试了两种方法:

  1. 遍历表头(th)并对TH和TD执行.show()或.hide()。
  2. 遍历表头(th)并更改类来显示/隐藏TH和TD。

以下代码段实现了该功能。但是性能不太好,显示/隐藏20列需要大约5~10秒的时间,可能有80~120行的数据。

我想知道是否有任何方法可以加快它的速度。

function ToggleHeadVisibility(showHide) {

    var index = 0;

    $('#' + gridViewName + ' thead th').each(function(index) {
        index++;
        if (showHide == "SHOW") {
            /*
            $('#' + gridViewName + ' th:nth-child(' + (index) + ')').show();
            $('#' + gridViewName + ' td:nth-child(' + (index) + ')').show();
            */
            $('#' + gridViewName + ' th:nth-child(' + (index) + ')').removeClass('columnHide');
            $('#' + gridViewName + ' td:nth-child(' + (index) + ')').removeClass('columnHide');
        } else if (showHide = "HIDE") {
            /*
            //if (showColumnArray.has($(this).get(0).innerHTML)) {
            if (showColumnArray.has($(this).attr('title'))) {
            $('#' + gridViewName + ' th:nth-child(' + (index) + ')').show();
            $('#' + gridViewName + ' td:nth-child(' + (index) + ')').show();
            }
            else {
            $('#' + gridViewName + ' th:nth-child(' + (index) + ')').hide();
            $('#' + gridViewName + ' td:nth-child(' + (index) + ')').hide();
            }
            */
            if (showColumnArray.has($(this).attr('title'))) {
                $('#' + gridViewName + ' th:nth-child(' + (index) + ')').removeClass('columnHide');
                $('#' + gridViewName + ' td:nth-child(' + (index) + ')').removeClass('columnHide');
            } else {
                $('#' + gridViewName + ' th:nth-child(' + (index) + ')').addClass('columnHide');
                $('#' + gridViewName + ' td:nth-child(' + (index) + ')').addClass('columnHide');
            }

        }
    });
}

1
一些有趣的显示/隐藏性能比较 - Eatdoku
6个回答

9

一些建议:

  1. 在构建表格时,为标题和数据单元格添加类似于 col1,col2,col3 等的css类。然后您只需执行 $("td.col1").hide(); 就可以隐藏相应的列。这比使用第n个子选择器要快。

  2. 在IE和Firefox中,您可以将 visibility: collapse 设置为 col 元素以折叠整列数据。这将更快。不幸的是,在Webkit浏览器中不支持此功能http://www.quirksmode.org/css/columns.html。您可以根据浏览器分支您的代码,使其至少在IE和Firefox中快速运行。

  3. 如果您的表格具有 table-layout: fixed,它可能会显著提高性能,因为与自动模式相比,您的浏览器不必每次触摸表格时都计算列的宽度。

  4. 考虑从DOM树中删除表格(通过 .remove()),执行批量显示/隐藏操作,然后再将其插入回去。这是无论何时您想对DOM树执行批量操作的通用规则。


我和楼主有着同样的问题,可能是一个更大的表格。我通过在表格建立时添加类(如上面所述点1)来解决这个问题,随后使用JavaScript动态更改这些类的CSS定义,而不是将类作为选择器来更改内联CSS样式。 - undefinederror

1

它在20~40行的情况下表现良好。我认为循环30个TH并不是一个大问题,可能更多是“th:nth-child”选择器的问题。它们只是太多了。也许有另一种方法? - Eatdoku

0

这是我用来隐藏网格中“第n个”列的代码片段...

  if (true) {
      $('th:nth-child(' + c + ')').show();
      $('td:nth-child(' + c + ')').show();                           
  }
  else {
      $('th:nth-child(' + c + ')').hide();
      $('td:nth-child(' + c + ')').hide();                          
  }

非常类似于你的,只是我使用了jQuery切换“显示/隐藏”;

它似乎可以在1秒内显示/隐藏400行列...

Borik


我尝试使用jQuery的show()和hide()函数代替添加/删除类,就像您在代码片段中所看到的那样(被注释掉的代码)。性能大致相同。 - Eatdoku

0

在缓存方面,你可以做很多事情。首先,缓存你的 gridView 容器:

var gridView = $('#' + gridViewName);

接着一行可以被缓存:

var row[0] = gridView.find('tr:nth-child(0)'); // Not sure the path is right, but you get the idea...

此外,使用set执行实际的隐藏操作,而不是使用.each()

row[0].addClass('columnHide'); // Calls addClass() on each element in the set

提前缓存元素集,而不是重复使用 $ 查询 DOM,并对元素集执行操作而不是循环,可以在性能方面大有裨益。


0

遍历行和列总是会减慢速度。尝试直接操作CSS规则以避免在JavaScript中进行迭代,并强制浏览器为您执行。

查看插件jQueryRulejQueryCSSRule

如果您组合所有规则,则直接操作CSS规则可能会有益。这里有一个带有500行和50列的快速测试。大部分时间都花费在重新渲染上,而在JavaScript函数内花费的时间平均为200-300毫秒(在Chrome上),0毫秒(在Firefox上)。目前它使用标准API,但将其扩展到IE很容易。

它的工作原理是在文档中创建一个新的<style>节点,并在其中添加所有列操作。关键思想是在隐藏某些列时将所有规则合并为一个。因此,不是执行以下操作:

table tr :nth-child(1) { display: none; }
table tr :nth-child(4) { display: none; }
table tr :nth-child(7) { display: none; }

它执行以下操作:

table tr :nth-child(1), table tr :nth-child(4), table tr :nth-child(7) {
    display: none;
}

当需要显示所有列时,请删除上面隐藏特定列的规则。


0
我可以建议类似这样的东西吗?
$(function() {
    $('#show').click(function() {
        var i;
        for (i = 0; i < titles.length; i++)
        {
            ToggleHeadVisibility('SHOW', titles[i]);
        }
    });

    $('#hide').click(function() {
        var i;
        for (i = 0; i < titles.length; i++)
        {
            ToggleHeadVisibility('HIDE', titles[i]);
        }
    });
});

var titles = ['one', 'three', 'five'];

function ToggleHeadVisibility(showHide, title)
{
    var x = $('th[title=' + title + ']').index();
    var selectString = 'th:nth-child(' + (x + 1) + '), td:nth-child(' + (x + 1) + ')';
    var $set = $(selectString);

    if (showHide === "SHOW")
    {
        $set.show();
    }
    else if (showHide === "HIDE")
    {
        $set.hide();
    }
}

我认为问题实际上出在你的循环上。你正在遍历表格中的每一个th。如果你只想找到特定的那些,为什么不直接遍历你想要找的那些呢?

所以,这里发生的事情就是这样。在点击“显示”(或“隐藏”)按钮时,我们遍历标题数组,调用ToggleHeadVisibility。

在那个函数中,我们获取具有给定标题的第一个元素的索引,然后显示或隐藏nth-child(x)节点。

我已经在一个有6列、每次显示和隐藏3列,超过1000行的表格上运行了它。对于它所做的事情来说,速度相当快。

请注意,如果你的title不是唯一的,它只会在表格中找到第一个。


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