後端: 資料都給你了,分頁、排序、篩選你看著辦吧。。。

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