我在 bootstrap 中构建了一个大表,大约5,000行x 10列,我需要仅使用JavaScript快速过滤表中的特定属性。该表同时具有id列和属性列,即

id | attr | ...
---------------
2  |  X   | ...
3  |  Y   | ...
4  |  X   | ...

为了加快筛选过程,我建立了一个哈希表,该表将属性映射回列ID。因此,例如,我有一个映射:
getRowIds["X"] = [2,4]

用户可以在搜索框中输入属性“X”,然后哈希表查找包含“X”的对应行(在这种情况下为2和4),然后通过map操作调用以下函数:
this.hideRow = function(id) {
    document.getElementById(id).style.display="none"
}

this.showRow = function(id) {
    document.getElementById(id).style.display=""
}

由于允许用户选择多个属性(例如X,Y),因此此过程仍然很慢。

有没有更快的隐藏行的方法?

如果能以某种方式将表与DOM分离,进行更改然后重新附加,速度会更快吗?如何在javascript中执行此操作?

还有其他更有效/更智能的过滤方法吗?

谢谢 :)

最佳答案

使用AngularJS确实是一个好主意,
这样我们就可以使您的行变得如此简单

<tr ng-repeat="row in rowArray">
  <td>{{row.id}}</td>
  <td>{{row.attr}}</td>
</tr>

如果您只需要提供rowArray作为{id: 1, attr: 'X'}之类的对象数组,请参阅the documentation for ng-repeat directiveAngular的强大功能之一在于其极为紧凑的代码。

除此之外,Angular还具有强大的filter building library,可以在HTML内部即时过滤和排序行:
<tr ng-repeat="row in rowArray | yourCustomFilter:parameters">
  <td>{{row.id}}</td>
  <td>{{row.attr}}</td>
</tr>

话虽如此,将5K行放入数组显然是性能的拖累。这将在浏览器内存中创建一个巨大的HTML,但该HTML将不适合您的视口(viewport)。如果您仍然无法显示它,那就没有必要将其存储在内存中了。取而代之的是,您只希望内存中有可见部分,周围可能还有几行。

看看由提供的指令“滚动直到放下”
Angular UI Utils-它就是这样做的!

另一个答案中提到的分页肯定是无限滚动的有效替代方法。如果想深入了解分页与无限滚动的优点和缺点,网络上有很多文章。

特别是谈到您的代码,它还会影响其他性能。
例如,在每次通话中,此函数
document.getElementById(id).style.display="none"

将通过其id查找该元素的DOM,然后将查找其属性.style(如果JavaScript需要在Prototype链中上移,则可以拖动该属性)。通过将直接引用链接缓存到display属性(这是您真正需要的属性),可以明智地提高性能。

编辑。
通过在此处进行缓存,我的意思是预编译将hash与有趣的属性链接在一起的id:
hash[id] = document.getElementById(id).style.display

然后,您可以通过简单的设置来切换样式:
hash[id] = 'none'
hash[id] = 'block'

这种计算hash的方法假定您的元素都在DOM内,这对性能不利,但是有更好的方法!

jQuery这样的库,当然还有Angular :),可以让您使用其完整样式属性(但为)来创建HTML元素,而无需将其附加到DOM 上。这样,您就不会过载浏览器的容量。但是您仍然可以缓存它们!因此,您将缓存HTML(但不包括DOM)元素及其显示,如下所示:
elem[id] = $('<tr>' +
  '<td>' + id + '</td>' +
  '<td>' + attr + '</td>' +
</tr>');

display[id] = elem[id].style.display;

然后将元素附加/分离到DOM,并使用显示缓存更新其display属性。

最后要注意的是,为了获得更好的性能,您希望首先将您的行连接到一个 bundle 包中,然后才将其附加在一个跳转中(而不是一个一个地附加)。原因是,每次更改DOM时,浏览器都必须进行大量重新计算才能正确调整所有其他DOM元素。发生了很多事情,因此您希望尽可能减少这些重新计算。

发布编辑。

举例说明,如果您的DOM中已经存在parentElement,并且您想附加一个新元素数组
elementArray = [rowElement1, ..., rowElementN]

您想要的方式是:
var htmlToAppend = elementArray.join('');

parentElement.append(htmlToAppend);

而不是一次循环附加一个rowElement的循环。

另一个好的做法是在附加之前对hide进行parentElement,然后仅在一切准备就绪时显示。

关于javascript - 如何使用纯Java脚本过滤非常大的引导表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29571578/

10-11 23:25
查看更多