後端: 資料都給你了,分頁、排序、篩選你看著辦吧。。。
theme: Chinese-red
持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第1天,點選檢視活動詳情
前言
後端一口氣返回了全部的資料,不多不少,也就十幾萬條資料,問:前端應該怎麼辦?
某個專案碰到了這個問題,一般十幾萬條資料不可能一口氣給到前端,一是請求時間會比較長,使用者體驗不好;二是前端不可能一次性顯示這麼多資料,通常都需要分頁顯示,保障頁面的流暢,所以只需要獲取一部分顯示的資料就夠了。
但真碰上了,只能想辦法解決了,肯定是不可能一次性將全部資料顯示出來,必須進行分頁處理。
關鍵在於,前端怎麼將這些資料進行分頁、排序、篩選。
以下是個人的思路,希望大佬多多指點。
技術棧
Vue
前置工作
首先,使用四個數組儲存資料,每個陣列儲存的資料也許相同,也許不同,各自有各自的用途,如下:
1. originDataList
: 儲存全部原始資料的陣列;
2. originSortDataList
: 該陣列的資料與 originDataList
一致,但是該陣列經過了排序處理,用於篩選操作;
3. showAllDataList
: 全部可展示的資料,該陣列是經過排序,篩選之後,可用於展示的全部資料的合集;
4. showDataList
: 真正渲染到頁面上資料集合,即 showAllDataList
的分頁資料;
分頁
分頁處理是最簡單的,根據上面定義的四個陣列來看,就是從 showAllDataList
中,根據 pageSize
(頁面單次顯示的資料)和 pageNumber
(頁碼),取出指定範圍內的資料,賦值給 showDataList
渲染到頁面上即可,主要程式碼如下:
js
function getShowDataList () {
// 確定起始索引
const startIndex = (this.pageSize - 1) * this.pageNumber
this.showDataList = this.showAllDataList.slice(startIndex, startIndex + this.pageNumber)
}
因為真正渲染到頁面上的資料,都是從
showAllDataList
中取出的,所以不管是排序還是篩選,最終都是對showAllDataList
進行修改,然後通過分頁的函式進行取值渲染。
排序
排序也不難,無非就是對使用者指定的欄位進行升序或者降序即可。
應用到專案中,就是對 showAllDataList
進行排序處理,根據排序要求,對 showAllDataList
進行相應的處理。
大概程式碼如下:
js
/**
* 排序
* @param { String } key 需要排序的屬性名稱
* @param { 'asc' | 'desc' | '' } order 排序方式
*/
function sortList (key, order) {
// 如果 order 為 '',即不指定排序,重置 showAllDataList
if (!order) {
// 注意:至少需要進行一層淺拷貝,不然會更改 原始資料的陣列
this.showAllDataList = [...this.originDataList]
} else {
// 排序處理
order === 'asc'
? this.showAllDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? 1 : -1)
: this.showAllDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? -1 : 1)
}
// 更改渲染資料
this.getShowDataList()
}
至此,基本實現了排序的功能,當然,具體的排序實現因人而異,不再贅述。
originSortDataList
這個陣列需要經過排序處理,供篩選功能使用,所以對showAllDataList
進行排序的同時,也需要對originSortDataList
進行排序。
加上 originSortDataList
之後,程式碼如下:
js
/**
* 排序
* @param { String } key 需要排序的屬性名稱
* @param { 'asc' | 'desc' | '' } order 排序方式
*/
function sortList (key, order) {
// 如果 order 為 '',既不指定排序,重置 showAllDataList
if (!order) {
this.showAllDataList = [...this.originDataList]
this.originSortDataList = [...this.originDataList]
} else {
// 排序處理
order === 'asc'
? this.showAllDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? 1 : -1)
: this.showAllDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? -1 : 1)
order === 'asc'
? this.originSortDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? 1 : -1)
: this.originSortDataList.sort((itemA, itemB) => itemA[key] > itemB[key] ? -1 : 1)
}
// 更改渲染資料
this.getShowDataList()
}
篩選
經過上面的處理,篩選就變得十分簡單,直接從 originSortDataList
中挑選出符合篩選條件的資料,組成新的陣列,賦值給 showAllDataList
即可。
主要程式碼如下:
js
/**
* 篩選
* @param { String } key 需要排序的屬性名稱
* @param { Number | String | Boolean } value 篩選值
*/
function filterList (key, value) {
// 不存在 value,則不進行任何篩選操作
if (value === '') {
// 淺拷貝,避免對 showAllDataList 進行修改會影響到 originSortDataList
this.showAllDataList = [...this.originSortDataList]
} else {
// 篩選的資料從 originSortDataList 中取出
this.showAllDataList = this.originSortDataList.filter(item => {
// 根據實際專案進行判斷篩選
})
}
// 更改渲染資料
this.getShowDataList()
}
為什麼不直接從
originDataList
或者showAllDataList
進行篩選? 1. 因為originDataList
的資料不會改變,因為排序的重置功能需要原始資料才能實現;而如果使用originDataList
,當排序和篩選同時執行時,篩選從originDataList
取值,則排序會失效。 2.showAllDataList
本身不一定包含著全部的資料,它的功能就是儲存所有可展示的資料,篩選過後,如果存在某些資料不符合要求,則不會儲存在showAllDataList
中,如果使用showAllDataList
進行篩選,會有遺漏。