我在 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
directive。 Angular
的强大功能之一在于其极为紧凑的代码。除此之外,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/