本帖最后由 Crystal.Li 于 2021-8-16 14:27 编辑
在报表设计过程有时候会遇到大数据量的报表展示,那么对于大数据量的报表展示,如果一次性把所有数据加载到页面上,那势必会造成页面卡顿、反应慢等性能问题。那么对于这种大数据量的报表展示我们如何该做性能优化呢?
一、问题背景
前端性能优化一直是一个比较大的话题,实际项目中可能会遇到很多关于性能的问题,常见的优化手法也很多,比如合并JS/CSS文件、减少http请求、懒加载、图片压缩等。在这里我们只聚焦于当数据量比较大的时候,我们该如何去做性能优化。假如后端的小哥哥小姐姐们将几万条数据丢给前端,我们拿到之后该怎么做呢?其实核心思想就是分段去展示数据!每次只加载可视区域的报表数据,当翻到下一页时再取下一页的数据进行展示。这样每次报表渲染的时候,只会渲染当页可见的dom元素,不会一次性把几万行报表数据渲染加载到页面上。
二、优化实战
那么落到实际该怎么做呢?这里我就以ActiveReports JS纯前端报表控件为例,来看一下在AR JS中如何展示大数据量报表。
1、自定义报表翻页按钮
分页加载报表数据,首先要自定义翻页按钮,当点击到下一页时,再去加载下一页的数据。ARJS提供了自定义翻页按钮的功能,所以这里先添加自定义按钮:
- const prevPageButton = {
- key: '$prevPageButton',
- text: "上一页",
- title: "prevPageButton",
- enabled: true,
- action: function () {}
- };
- const nextPageButton = {
- key: '$nextPageButton',
- text: "下一页",
- title: "nextPageButton",
- enabled: true,
- action: function () {}
- };
- const pageCount = {
- key: '$pageCount',
- text: `1/ ${totalPage}`,
- title: "pageCount",
- enabled: true
- };
复制代码 这里我定义了三个按钮,分别为“上一页”、“当前页”、“下一页”,其中“当前页”在翻页过程中会不断计算更新页面展示。然后将几个按钮要添加到ARJS 的viewer对象上:- viewer = this.$refs.reportViewer.Viewer();
- this.designerHidden = true;
- [ prevPageButton, pageCount, nextPageButton ].forEach((item) => {
- viewer.toolbar.addItem(item);
- })
- viewer.toolbar.updateLayout({default: ["$zoom", "$split", "$print","$prevPageButton", "$pageCount", "$nextPageButton"]});
复制代码
api的使用部分不再赘述,可以参考帮助文档:https://demo.grapecity.com.cn/ac ... tarted/ResourceGuid
2、分页展示数据
自定义按钮之后我们就需要去实现如何分页取数据,只展示当页数据。我们需要提前计算好每页能够展示多少条数据,比如我这里每页展示29条数据,所以每次从后端数据中取出29条数据来传给报表展示:
- let currentPage = 1;
- //每页展示的数据条数
- let once = 29;
- //计算需要展示的总页数
- const totalPage = salesData.length % once ? Math.floor(salesData.length / once) + 1 : Math.floor(salesData.length / once);
复制代码 初始预览时,传给报表前29条数据:
- openReportView(salesData.slice(0, 29));
- function openReportView(data) {
- definition.DataSources[0].ConnectionProperties.ConnectString = "jsondata=" + JSON.stringify(data);
- viewer.open(definition);
- }
复制代码 在翻页时再判断逻辑,将数据分段传给报表文件,这里逻辑需要定义在之前定义的button提供的action接口中,同时定义好翻页数据逻辑之后,我们也需要更新当前页的展示:- const prevPageButton = {
- key: '$prevPageButton',
- text: "上一页",
- title: "prevPageButton",
- enabled: true,
- action: function () {
- if(currentPage === 1) {
- return null;
- } else {
- currentPage --;
- let data = salesData.slice((currentPage-1) * once, currentPage * once);
- openReportView(data);
- pageCount.onUpdate([], pageCount);
- }
- }
- };
- const nextPageButton = {
- key: '$nextPageButton',
- text: "下一页",
- title: "nextPageButton",
- enabled: true,
- //action接口中实现更新每次展示的数据逻辑
- action: function () {
- if(currentPage === totalPage) {
- return null;
- } else {
- currentPage ++;
- let data = currentPage === totalPage ? salesData.slice((currentPage-1) * once, salesData.length) : salesData.slice((currentPage-1) * once, currentPage * once);
- openReportView(data);
- //调用更新展示当前页号的逻辑
- pageCount.onUpdate([], pageCount);
- }
- }
- };
- const pageCount = {
- key: '$pageCount',
- text: `1/ ${totalPage}`,
- title: "pageCount",
- enabled: true,
- //实现更新页号的逻辑
- onUpdate: function (args, currentItem) {
- currentItem.text = `${currentPage}/${totalPage}`;
- }
- };
复制代码
三、效果对比
至此我们分页展示大数据量报表的逻辑就已经实现完成了。让我们来对比看看效果吧!
未分页展示数据前:
分页展示数据:
可以看到上方两个GIF图有明显的对比,未分页前点击预览之后有两秒左右的空白加载时间,而分页之后,点击预览数据立刻呈现出来了。这里我的测试数据有一万多行,那么当后端传回的数据超过一万或者更多时,前期加载时间会更多,此时这种分页加载的方式就十分有用,更快的让数据呈现在用户眼前。
完整demo:
|