後端: 數據都給你了,分頁、排序、篩選你看着辦吧。。。
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
進行篩選,會有遺漏。