In the report design process sometimes encountered large amount of data report display, so for the large amount of data report display, if all the data is loaded on the page, it is bound to cause page lag, slow response and other performance problems. So how do we optimize performance for this kind of large data presentation?

First, background

Front-end performance optimization is always a big topic, there may be a lot of performance problems in actual projects, and there are many common optimization methods, such as merging JS/CSS files, reducing HTTP requests, lazy loading, image compression, etc. Here we will focus only on how to optimize performance when the data volume is large. What if the little brothers and sisters on the back end throw tens of thousands of pieces of data to the front end, what do we do when we get them? In fact, the core idea is to show data in segments! Only load the report data of the visual area each time, and then take the data of the next page for display when turning to the next page. This will render only the DOM elements visible to the page each time the report is rendered, rather than loading tens of thousands of lines of report data onto the page at once.

Second, optimize the actual combat

So how do you actually do that? Here I will take ActiveReports JS pure front-end report control as an example to see how to display large data reports in AR JS.

1. Custom report page turning button To load report data in pages, you must first customize the page turning button, and then load data on the next page when you click to the next page. ARJS provides the ability to customize the page turning button, so here we add the custom button:

Const prevPageButton = {key: '$prevPageButton', text: "previous page ", title: "prevPageButton", enabled: true, Action: function () {} }; Const nextPageButton = {key: '$nextPageButton', text: "nextPageButton", title: "nextPageButton", enabled: true, Action: function () {} }; const pageCount = { key: '$pageCount', text: `1/ ${totalPage}`, title: "pageCount", enabled: true };Copy the code

Here, I define three buttons, namely “previous page”, “Current page” and “Next page”. The “current page” will constantly calculate and update the page display during the page turning process. Then add a few buttons to the ARJS viewer object:

 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"]});
Copy the code

Using part of the API are outside, you can refer to help document: demo.grapecity.com.cn/activerepor…

2. Display data in pages

After customizing the button, we need to implement how to paginate the data and only display the data on the page. We need to calculate in advance how many pieces of data can be displayed on each page. For example, I present 29 pieces of data on each page, so I take 29 pieces of data from the back-end data every time and pass them to the report display:

let currentPage = 1; // let once = 29; Const totalPage = Salesdata.length % once? Math.floor(salesData.length / once) + 1 : Math.floor(salesData.length / once);Copy the code

During the initial preview, the first 29 pieces of data are passed to the report:

openReportView(salesData.slice(0, 29));

function openReportView(data) {
      definition.DataSources[0].ConnectionProperties.ConnectString = "jsondata=" + JSON.stringify(data);
      viewer.open(definition);
}
Copy the code

The logic should be defined in the action interface provided by the button previously defined. At the same time, after defining the page turning data logic, we also need to update the display of the current page:

Const prevPageButton = {key: '$prevPageButton', text: "previous page ", 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: "nextPageButton", title: "nextPageButton", enabled: 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); // Call the logical pagecount. onUpdate([], pageCount); }}}; const pageCount = { key: '$pageCount', text: `1/ ${totalPage}`, title: "pageCount", enabled: OnUpdate: function (args, currentItem) {currentitem. text = '${currentPage}/${totalPage}'; }};Copy the code

Third, effect comparison

At this point we paginated display large data volume report logic has been completed. Let’s compare and see the effect!

Before displaying data without paging:

Paging display data:

You can see the contrast between the two giFs above. There is a blank load time of about two seconds after clicking preview before pagination, but after pagination, clicking Preview immediately renders the data. My test here had over 10,000 rows of data, so when the back end returned 10,000 or more data, the pre-load time would be much higher, and this pagination would be useful to get the data to the user more quickly.