具有大量行的表更新速度很慢

Table with large number of rows is slow to update

本文关键字:更新 速度      更新时间:2023-09-26

我有一个页面,里面有一个非常大的表(有几千行)。

表显示由某些过滤器指定的数据子集。当其中一个过滤器发生变化时,我需要更新表。

基本上,有几个复选框和一个文本框,每当其中一个更改时,我重新加载表以只显示符合用户指定条件的行。

我通过清除表并重新加载匹配过滤器的行来做到这一点。这是有效的,但已被证明是非常缓慢的。

下面是我的javascript代码:

function reloadTable() {
    var tablebody = document.getElementById("tablebody");
    while(tablebody.hasChildNodes()) tablebody.removeChild(tablebody.firstChild);
    filter = new FilterChecker();
    for (var i=0;i<rows.length;i++) {
        if (filter.isVisible(rows[i]))
            addRowToTable(rows[i]);
    }
}

有办法使它更快吗?

好吧,抱歉耽误了,我工作太忙了。我想出了一套很好的逻辑来说明你需要什么。

小提琴我创建了一些简单的html来说明这一点。它包含两个下拉菜单来模拟过滤器和8个数据行来模拟您的数据网格。

<div id="body">
<select id="filterA" class="filter" name="states">
    <option value="filterACT">Connecticut</option>
    <option value = "filterAMA">Mass</option>
</select>
<select id="filterB" class="filter" name="towns">
    <option value="filterBBT">Big Town</option>
    <option value = "filterBST">Small Town</option>
</select>
<div id="grid">
    <div class="row filterACT filterBBT">BigTown CT 1</div>
    <div class="row filterACT filterBBT">BigTown CT 2</div>
    <div class="row filterACT filterBST">SmallTown CT 1</div>
    <div class="row filterACT filterBST">SmallTown CT 2</div>
    <div class="row filterAMA filterBBT">BigTown MA 1</div>
    <div class="row filterAMA filterBBT">BigTown MA 2</div>
    <div class="row filterAMA filterBST">SmallTown MA 1</div>
    <div class="row filterAMA filterBST">SmallTown MA 2</div>
</div>
</div>
</br>
<hr/>
<div>LOG</div>
<hr/>
<div id="log"></div>

logdiv只是为了显示一个输出,我认为这会很有帮助。每一行都由类"row"标识,后面跟着另一系列类。这些类帮助确定它们的筛选器数据是什么。您需要在构建网格时以编程方式设置它。此外,这些类名必须与过滤器选项值匹配。您可以看到,第一行有来自filterA中的第一个选项和filterB中的第一个选项的类。

现在,javascript有点冗长,但您可以重构您的内心内容。有时我发现,当你试图理解事情的时候,如果事情是明确的,会更容易一些。同样,不可否认的是,我会用jQuery来做这件事,所以我的纯Javascript不是那么清晰。

var elements = document.getElementsByClassName('filter');
writeToLog("Filter elements found: " + elements.length);
for(var e = 0;e < elements.length;e++)
{
    elements[e].onchange =function() {   
        writeToLog('Filter event fired for id:'+this.id);
        filterChange();
    };
}

首先我得到所有的元素与过滤器类,这将是你的过滤器。然后遍历它们并设置它们的onchange事件以调用filterChange()方法。writeToLog()方法调用只是为了输出。

    function filterChange() {
    var filterClasses = [];
    for(var i = 0;i<elements.length;i++) {
        writeToLog('Pushing ('+elements[i].value+') into filter class variable.');
        filterClasses.push(elements[i].value);        
    }

在函数的第一部分,我得到所有的选择过滤器选项值,并把它们放入一个数组。

    writeToLog('Filter classes: ' + filterClasses);
    var rows = document.getElementsByClassName('row')
    writeToLog('Row count: ' + rows.length);

然后我得到所有的行,在我的网格中,并开始迭代它们:

    for(var j = 0;j<rows.length;j++)
    {
        writeToLog('Checking row: ' + rows[j].className);
        var rowIsHidden = false;

一旦我有了一行,在循环中,我迭代数组中的过滤器类,看看这一行的类是否有它。如果不是,我将rowIsHidden设置为true,否则保持false。

        for(var k = 0;k<filterClasses.length;k++)
        {
            writeToLog('Checking for class: ' + filterClasses[k]);
            if(rows[j].className.indexOf(filterClasses[k]) < 0)
            {
                writeToLog('Class not found, hide this row.');
                rowIsHidden = true; 
                break;
            }
        }

在循环移动到下一行之前,我基于rowIsHidden值设置了显示样式。

        writeToLog('Row is hidden: ' + rowIsHidden);
        rows[j].style.display = rowIsHidden ? 'none' : 'block';
    }
}

无论如何,这可以被清理和优化,但我认为意图和逻辑是相当清楚的。希望这对你有所帮助,如果有任何问题,请随时提问:)