JavaScript百万行数据网格

226

我需要使用JavaScript在网格中呈现大量数据行(即数百万行)。

用户不应该看到分页或只能一次查看有限数量的数据。

相反,它应该显示所有数据都是可用的。

与其一次性下载所有数据,而是随着用户滚动网格而下载小块数据(即逐步加载)。

这些行将不会通过前端进行编辑,因此只读网格是可以接受的。

有哪些使用JavaScript编写的数据网格适用于这种无缝翻页?


1
@drozzy:我并没有“拒绝”任何东西。所有的解决方案,包括“编写自己的”解决方案,都将使用AJAX。问题是:有哪些数据网格支持无缝滚动数百万行。 - Rudiger
7
请翻译以下内容:Write your own. I am sure that the other ones are choking up because they just keep appending to the DOM. I think you will need a solution that removes rows as they scroll off the screen. That is the only way. You simply can't have a million table rows in the DOM and expect every browser to to display and scroll seamlessly in every environment. Be reasonable.请尽量准确且简洁地翻译,但不要进行解释或添加额外信息。请见下翻译:写你自己的代码。我相信其他的程序员停滞了是因为他们只是将数据不断地附加到DOM上。我认为你需要一种解决方案,当行从屏幕上滚动离开时,能够将其删除。这是唯一的方法。你不能期望在每个环境下都无缝地显示和滚动数百万行表格数据。请理性对待。 - Josh Stodola
2
@Rudiger:SlickGrid现在本来就支持无限数量的行。请参见http://github.com/mleibman/SlickGrid/tree/unlimited-rows 。一旦这个功能经过充分测试,它将被合并到主分支中。 - Tin
11
我对你目前所在的公司感到遗憾。需要说明的是,一个1920x1080像素的屏幕只能显示100万行,每次在滚动条上移动一个像素,屏幕将会跳动20行。去做一些可用性测试吧,别浪费时间了。 - Sleeper Smith
3
这个问题以及其前两个回答(至少)都非常有用。虽然可能会吸引到一些低质量的回答,但这绝对不应该关闭此问题。如果人们尝试重新实现它们自己,使用SlickGrid来解决这个问题可以节省许多麻烦和困难编码的时间。 - Sam Watkins
显示剩余14条评论
19个回答

192

(免责声明:我是SlickGrid的作者)

更新 此功能已在SlickGrid中实现。

请参见http://github.com/mleibman/SlickGrid/issues#issue/22,了解有关使SlickGrid适用于更大行数的持续讨论。

问题在于SlickGrid没有为滚动条本身提供虚拟化支持-可滚动区域的高度设置为所有行的总高度。当用户滚动时,仍会添加和删除行,但滚动本身是由浏览器完成的。这使得它非常快速且平滑(onscroll事件非常慢)。缺点是浏览器的CSS引擎存在一些限制,限制了元素的潜在高度。对于IE而言,这个限制是0x123456或1193046像素。对于其他浏览器,限制要高一些。

"largenum-fix"分支中有一种实验性的解决方法,通过将滚动区域填充为“页面”,高度设置为1M像素,并在这些页面内使用相对定位来显著提高该限制。由于CSS引擎中的高度限制似乎与实际布局引擎中的限制不同且显着较低,因此这使我们的上限要高得多。

我仍在寻找一种方法,以获得无限数量的行数,而又不放弃SlickGrid目前对其他实现所具有的性能优势。

Rudiger,您能详细说明您是如何解决这个问题的吗?


1
我发现SlickGrid是最吸引人的 - 特别是如果你使用jQuery。恭喜!(尤其是对于伟大的态度和坚持不懈。) :-) - Andras Vass
我正在尝试使用SlickGrid来显示Excel表头,但是当列数过多时,我发现SlickGrid只优化了行的滚动而没有优化列的滚动。我还注意到,当列数超过120列左右时,SlickGrid会将新行放在新的一行中。是否可以在文件中设置最大行数? - oneiros
1
SlickGrid v2.1使用虚拟滚动来处理列和行,同时也解决了溢出列的问题。 - Tin
@Tin - 这与我的方法类似;我比时代领先多年!“一种用于将无限滚动构建到Web应用程序中的懒惰块布局原语。” https://docs.google.com/document/d/1-tbcMJV8wNbX2g5ehNIcE_1W7Kj_B3g9w1BrUgHnh3U/preview?pli=1 - Rudiger
@Rudiger 是的,我大约一个月前在 Blink 组看到过这个,但我不太确定它如何适应整个情况。懒惰布局是针对实际存在于 DOM 中的元素进行操作的,而我们实际上无法这样做。请详细说明一下 :) - Tin
@Tin,这个网格控件能处理数百列、数百万行的数据吗?我尝试过很多工具,但一旦列数增加到100-200,它们的性能就会达到极限。谢谢。 - NKD

85

https://github.com/mleibman/SlickGrid/wiki

"SlickGrid利用虚拟渲染使您可以轻松处理数十万个项目,而不会出现任何性能下降。实际上,使用具有10行和100,000行的网格之间没有性能差异。"

一些亮点:

  • 自适应虚拟滚动(处理数十万行)
  • 极快的渲染速度
  • 富单元格的后台呈现
  • 可配置和可自定义
  • 完整键盘导航
  • 列大小调整/重新排序/显示/隐藏
  • 列自适应和强制适应
  • 可插入的单元格格式化程序和编辑器
  • 支持编辑和创建新行。" 由mleibman提供

免费(MIT许可证)。 它使用jQuery。


它正常工作直到精确的131,001行...也就是说,有一行代码像这样:data.length = Math.min(131000,parseInt(resp.total)); ... 当然,那是硬编码的原因 :( - Rudiger
6
我花了一些功夫,但我做了一些更改,使得网格不再依赖于“data”数组的长度。这是一个权宜之计,但我让响应填充到一个“bigdata”数组中,而较小的“data”从“bigdata”数组中提取。程序的其余部分使用较小的数据数组,除了滚动条测量和其他一些现在对大量行数没有限制的地方。总的来说,比起编写自己的程序要容易得多。 - Rudiger
9
@Rudiger:SlickGrid现在原生支持无限行数。请参见http://github.com/mleibman/SlickGrid/tree/unlimited-rows。一旦经过充分测试,它将被合并到主分支中。 - Tin
我正在尝试使用SlickGrid来显示Excel表头,但是当列数过多时,我发现SlickGrid只优化了行的滚动而没有优化列的滚动。我还注意到,当列数超过120列左右时,SlickGrid会将新行放在新的一行中。是否可以在文件中设置最大行数? - oneiros
如果你想要快速的东西,不要依赖于使用jquery来做核心事情的任何东西,而是使用innerHTML而不是DOM append。在慢速计算机上,Javascript滚动条可能比浏览器滚动条慢得多,避免复杂的CSS规则,并且你应该花时间简化单行的布局。微小的优化在这种情况下可能是显著的。这只是改善性能的一般实践。jsPerf.com是你的朋友。 - Vitim.us

38

在我看来,最好的网格如下:

在我看来,最好的三个选项是 jqGrid、jqxGrid 和 DataTables。它们可以使用数千行数据并支持虚拟化。


1
列表中加1,虽然比较方面没有太多内容。一个好的开始是为每个添加提交数量-目前Flexigrid为33,而SlickGrid为491。 - Dan Dascalescu
12
忘掉SO的5分钟评论编辑限制吧。#1- jqGrid - 1000多次提交;#2- 752次提交,针对DataTables;#3- 491次提交,针对SlickGrid;#4- 33次提交,针对Flexigrid。Ingrid- 自2011年6月以来没有更新。jqGridView- 自2009年以来没有更新 - Dan Dascalescu
3
在之前的评论基础上,我在这里提供每个项目的 fork 数量:#1 - SlickGrid - 670 个 fork;#2 - jqGrid - 358 个 fork;#3 - Flexigrid - 238 个 fork;#4 - DataTables - 216 个 fork;#5 - Ingrid - 41 个 fork;#6 - jqGridView - 0 个 fork。 - ljs.dev
1
请查看http://nexts.github.io/Clusterize.js/。 - Denis
1
可以评论一下,Slickgrid仍然很活跃和健康,但上面提到的mleibman代码库已经停止维护。新链接:http://github.com/6pac/SlickGrid(mleibman在他的代码库的最后一个注释中引用了它),或者www.slickgrid.net。 - Ben McIntyre
添加 Smart.Grid https://www.htmlelements.com/demos/grid/overview/ - scripto

24

我并不想引发口水战,但是假设你的研究人员是人类,你并不像你想象中那样了解他们。仅仅因为他们拥有petabytes的数据并不能使他们有能力以任何有意义的方式查看甚至数百万条记录。他们可能会说他们想要看到数百万条记录,但那只是愚蠢的想法。让你最聪明的研究员做一些基本的计算:假设他们花费1秒钟查看每个记录。以这种速率,需要1000000秒,相当于超过六周(每周40小时工作时间,没有吃饭或上洗手间的休息时间)。

他们(或者你)真的认为一个人(查看网格的人)能够集中精力做到那样的事情吗?他们在那1秒钟内确实能完成很多工作吗,还是(更有可能)把他们不想要的东西筛选掉了?我怀疑在查看“合理大小”的子集之后,他们可以向你描述一个自动过滤掉那些记录的过滤器。

正如paxdiablo、Sleeper Smith和Lasse V Karlsen所暗示的那样,你(和他们)还没有深入思考这些要求。好的一面是,现在你已经找到了SlickGrid,我相信对于那些过滤器的需求立即变得明显。


2
需要数百万行并不总是为了查看它们。有时客户想要部分记录的转储,以在他们自己的数据分析系统中运行。 - cbmeeks
10
如果这是他们自己分析的数据转储,那么它不会显示在网页上的网格中,对吧? - Steven Benitez
6
我不必一次看到它们所有。这就是列排序和“Ctrl+F”的用途。另一个选择(分页、网站搜索)要糟得多。只需查看 StackOverflow 以滚动查看问题或答案,Reddit 以滚动查看用户的评论记录。排序和即时搜索提供了 Windows Explorer 具有但网站缺乏的强大功能。 - Ian Boyd

14

我可以非常肯定地说,你不需要向用户展示成百万行的数据。

全世界没有一个用户能够理解或者管理那么多的数据集,即使你在技术上成功实现了这一点,也不能解决用户已知的任何问题。

相反,我建议关注用户为什么想要看到这些数据。用户不会只是为了看数据而看数据,通常都是在寻求特定问题的答案。如果你专注于回答这些问题,就能更接近解决实际问题的目标。


17
我的用户是研究人员,习惯于处理千万亿字节的数据。我认为我比你更了解我的用户,但你在一般情况下肯定是正确的。至于为什么,这个数据网格只是管理大数据工具集合中的一部分。 - Rudiger

7

ExtJs,确实如此。它基本上是专门为数据展示构建的。 - KdgDev
1
ExtJs太好了,我想哭,因为它不是基于jQuery构建的。 - James Westgate
现在您可以仅加载与ExtJS相关的网格部分,以便将ExtJS网格添加到应用程序中不会太重。但是,您仍然需要考虑外观上的差异,并使用ExtJS主题化方式来处理该组件。 - JD Smith

7

(免责声明:我是w2ui的作者)

最近,我撰写了一篇关于如何使用JavaScript网格处理100万条记录的文章 (http://w2ui.com/web/blog/7/JavaScript-Grid-with-One-Million-Records)。我发现最终有3个限制阻止了它的进一步提高:

  1. div的高度有一个限制(可以通过虚拟滚动来克服)
  2. 在100万条记录左右,排序和搜索等操作开始变慢
  3. 由于数据存储在JavaScript数组中,RAM受到限制

我已经测试过拥有100万条记录的网格(IE除外),表现良好。请查看文章以获取演示和示例。


有了这一百万条记录,你的HTML页面大小为3MB。但是当我加载我的数据时,页面大小为15MB。w2ui能处理吗?我需要所有数据进行一些计算。 - Chetan S. Choudhary

6

dojox.grid.DataGrid提供了JS数据抽象,因此您可以使用提供的dojo.data存储库将其连接到各种后端或编写自己的存储库。显然,您需要一个支持随机访问这么多记录的存储库。DataGrid还提供了完整的可访问性。

编辑:这里有一个链接到Matthew Russell的文章,它应该提供您所需的示例,使用dojox.grid查看数百万条记录。请注意,它使用旧版本的网格,但概念是相同的,只是存在一些不兼容的API改进。

哦,而且它是完全免费开源的。


4

以下是可以应用的一些优化方法,可以加快速度。只是随便想想。

由于行数可能达到数百万,因此您需要一个缓存系统,专门针对来自服务器的JSON数据。我无法想象有人想要下载所有X百万项,但如果他们这样做,那将是一个问题。这个小测试在Chrome上对于一个包含20M+整数的数组会不断地崩溃。

var data = [];
for(var i = 0; i < 20000000; i++) {
    data.push(i);
}
console.log(data.length);​

你可以使用LRU或其他缓存算法,并对你愿意缓存的数据量设置上限。
对于表格单元格本身,我认为构建/销毁DOM节点可能很昂贵。相反,你可以预定义X个单元格,每当用户滚动到新位置时,将JSON数据注入这些单元格中。滚动条几乎没有直接关系到需要表示整个数据集的空间(高度)。你可以任意设置表格容器的高度,比如5000px,并将其映射到总行数。例如,如果容器高度为5000px,总共有1000万行,则起始行≈(scroll.top/5000)*10M,其中scroll.top表示从容器顶部滚动的距离。这里有一个小演示
为了检测何时请求更多数据,最好使用一个对象作为中介来监听滚动事件。这个对象会跟踪用户滚动的速度,并在看起来像用户正在减缓或完全停止时,为相应的行发出数据请求。以这种方式检索数据意味着您的数据将是分散的,因此缓存应该考虑到这一点。
此外,浏览器对最大传出连接的限制可能起重要作用。用户可能会滚动到某个位置,触发一个AJAX请求,但在请求完成之前,用户可以滚动到其他某个位置。如果服务器响应不够迅速,请求将排队等候,应用程序看起来会无响应。您可以使用请求管理器来管理所有请求,并取消挂起的请求以腾出空间。

4

2
Dojo 还提供了一个很好的网格:http://docs.dojocampus.org/dojox/grid/DataGrid - Select0r
很遗憾在这里看到jqgrid无法工作...他们从他们的网站http://trirand.net/链接到http://stackoverflow.com/questions/tagged/jqgrid - Rudiger

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