0

我有一个表,它有一个切换来显示/隐藏符合某些条件的各种行,我正在使用以下 JS 来实现我想要的(JSFiddle);

function resetRows() {
    var i = 1,
        tds;
    var start = new Date().getTime();
    $('td').removeClass('even odd');

    $.each($('tr'), function (key, index) {
        // loop through each table row skipping the first row which will be the title
        tds = $(this).find($('td'));
        if ($(this).is(':visible') && key > 0) {
            if (i % 2 === 0) {
                tds.addClass('even');
            } else {
                tds.addClass('odd');
            }
            // find the .index class and reset it's value
            $(this).find($('.index')).html(i);
            i++;
        }
    });
    var end = new Date().getTime();
    var time = end - start;
    console.log('time taken: ' + time);
}

$(function () {

    // show/hide failed
    $('#showHideFails').on('click', function () {
        if ($('.failed').eq(0).is(':visible')) {
            $('.failed, .ins').hide();
            $('.shTxt').html('Show all');
            resetRows();
        } else {
            $('.failed, .ins').show();
            $('.shTxt').html('Hide failed');
            resetRows();
        }
    });

});

我的问题是这段代码执行得很慢。js 小提琴相对较快,因为我的示例表只有 15 行。我的实际表有 100 行,可以更改为显示 1,000 行。

我添加了一个控制台日志来测试它执行了多长时间,并且在小提琴中隐藏行需要大约 15 毫秒,再次显示行需要大约 20-40 毫秒。

在我有 100 行的真实表上,这变为隐藏约 300-450 毫秒,显示约 500-600 毫秒。当尝试 200 行(分别为 1,200 和 2,00)时,这个数字增加了一倍以上。当我尝试 1,000 行时,我的浏览器几乎崩溃了。

我尝试更改我的代码,而不是更改 's 的类名,而是更改了td's 的类名,tr因为理论上这意味着 jQuery 处理所需的处理更少,但这几乎使执行时间增加了一倍,所以我恢复了到td

谁能告诉我如何让我的代码更有效率?获得我想要的功能有点令人沮丧,只是让它运行得很慢。

4

2 回答 2

2

使用这种元素迭代时,您应该将表与 DOM 分离。然后,您可以在任务期间向用户显示任何消息,例如加载程序。

http://jsfiddle.net/ZYsHL/6/

function resetRows($table) {
    var $loader = $('<div id="loader"/>').insertBefore($table),
        $tblContent = $table.detach(),
        i = 1,
        trs = $tblContent.find('tr'),
        tds = $tblContent.find('td').removeClass('even odd');
    var start = new Date().getTime();

    $.each(trs, function (key, index) {
        // loop through each table row skipping the first row which will be the title
        var tdsRow = $(this).find('td');

        if (!$(this).data('hidden') && key > 0) {
            if (i % 2 === 0) {
                tdsRow.addClass('even');
            } else {
                tdsRow.addClass('odd');
            }
            // find the .index class and reset it's value
            $(this).find('.index').html(i);
            i++;
            console.log(i);
        }
    });
    var end = new Date().getTime();
    var time = end - start;
    $loader.replaceWith($table);
    console.log('time taken: ' + time);
}

$(function () {

    // show/hide failed
    $('#showHideFails').on('click', function () {
        if ($('.failed').eq(0).is(':visible')) {
            $('.failed, .ins').data('hidden',true).hide();
            $('.shTxt').html('Show all');
            resetRows($('#table'));
        } else {
            $('.failed, .ins').data('hidden',false).show();
            $('.shTxt').html('Hide failed');
            resetRows($('#table'));
        }
    });

});
于 2013-06-10T10:02:30.190 回答
1

一些代码优化建议:

  1. 的使用.find()

    tds = $(this).find($('td'));是相同的tds = $(this).find('td')

    $('td') 导致 jquery在执行任何其他操作之前搜索整个 HTML 中的所有表格单元格

    但是您真正想要的是:当前行的所有单元格都可以使用 $(this).find('td')

  2. 删除“死”代码

    如果您在标题行中或该行已被隐藏,则您的行迭代函数不会执行任何操作。目前,您正在搜索该行中的单元格,即使它是隐藏的。

     $.each($('tr'), function (key, index) {
        if (false == $(this).is(':visible') || 0 == key) {
            // skip hidden rows and header row
            return;
        }
    
        // at this point we know that the current row is visible and not the header row
        tds = $(this).find($('td'));
        ...
     });
    
  3. 减少 jQuery 选择器

    据我所知,选择器是这里成本最高的部分。虽然这对于小数据来说不是问题,但它会影响大数据,比如有 1000 行的表等。尝试通过使用变量在可能的情况下重新使用选择器结果。

    将 $(this) 替换为变量:

    var currentRow = $(this);
    currentRow.is(':visible');
    currentRow.find('td');
    ...
    

这些是我到目前为止的想法。看到这个jsfiddle重写代码:http: //jsfiddle.net/5jVdh/3/

于 2013-06-10T10:27:06.767 回答