後端: 數據都給你了,分頁、排序、篩選你看着辦吧。。。

語言: CN / TW / HK

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 進行篩選,會有遺漏。