Client-side pagination with 120K items
On 2020/08/25 at 00:04
When developing global ranking feature for the leetcode ranking search project, I have to deal with the 120K users' ranking data. Since I don't want to maintain a server, I would like the ranking search website to be fully static which means I have to deal with these 120K users' data in client side purely.
I used BootstrapVue as my frontent component framework and it has a <b-table>
component for the table component which also has built-in client-side pagination feature to deal with data. However when loading 120K items into the table component, it makes the UI stop responding to anything!!
The problem is the <b-table>
component generates all the 120K DOM elements when loading the data and it would cause the UI freeze when updating the DOM. To conquer this problem, I leverage the provider functions feature which is originally designed for implementing server-side pagination.
In the provider function I fetch the data only once and slice and filter the data each time the table component calls the provider function to retrieve the data for a specific page. In this way, the browser only generate a page of DOM elements which is only 25 elements instead of 120K elements. So the UI can function smoothly and responsive!!
rankProvider: function(ctx) {
if (this.rank.length === 0) {
return axios.get('data/global-ranking.json')
.then(function (resp) {
this.rank = resp.data;
this.filteredRank = this.rank;
this.totalRows = this.rank.length;
let start = (this.currentPage - 1) * this.perPage;
return this.rank.slice(start, this.perPage);
}.bind(this));
} else {
if (this.lastFilter != ctx.filter) {
this.currentPage = 1;
ctx.currentPage = 1;
this.filteredRank = this.rank.filter(this.filterFunc);
this.totalRows = this.filteredRank.length;
this.lastFilter = ctx.filter;
}
let start = (ctx.currentPage - 1) * this.perPage;
return this.filteredRank.slice(start, start + this.perPage);
}
}