如圖所示,這是個常見的多選todolist
不過這里多了個要求,彈窗上下頁面切換的時候需要保留勾選結果
這其實也不難,但是如果每次都手動寫一遍卻有點惱人,這次捋一下思路,并把核心代碼記錄一下,方便下次翻找
核心思想
- 在服務器返回的數據之外再維護一個列表A,存儲被鉤上的數據
- 在請求接口時候給服務器返回數據鉤上已選的
- 點擊全選或者單個勾選(或取消勾選)時候再次把當前頁面的勾選數據同步給列表A
- 那如何同步呢?重點,后面針對性說同步函數
彈窗封裝
data數據說明
- data對應的數據有;
- params: 外部傳入接口請求的參數;
- single: 是否單選;
- pickedArr:承接外部傳入的已選中元素數組后變成已選元素數組
selectedItems:彈窗內已選中的元素數組;- form: 彈窗內查詢列表的參數;
1.對外提供show方法來調用,接受幾個參數,
1.1config.single是否支持單選
1.2.params 接口請求需要的額外參數
1.3.外面已選的列表(最好是完整列表,數組元素包括id和對應的文字)
1.4 根據1.3進行一些過濾(有時候彈窗是個二級彈窗,需要根據params參數進行置空或過濾)最后把過濾后的數組作為當前彈窗已勾選列表來存儲數據
show函數程序入口
初始化配置參數
初始化已選數據
請求列表
顯示彈窗
function show(config) {this.showMaterialPopup = true;const { params, single, pickedArr } = config;//配置參數覆蓋// Array.isArray(filterids) ? (this.filterids = []) : (this.filterids = []);params ? (this.params = params) : (this.params = {});single ? (this.single = true) : (this.single = false);Array.isArray(pickedArr) ? (this.pickedArr = pickedArr) : (this.pickedArr = []);/////////初始化彈窗的已選數據///////const firstPickItem = this.pickedArr[0];//根據params和已選中的第一個做一些判斷或者過濾//這里的代碼是個二級彈窗,可以參考,if (firstPickItem && firstPickItem.materialId && firstPickItem.materialId == params.materialId) {//把傳入已選上的元素的checked都鉤上this.selectedItems = this.pickedArr.map((item) => {item.checked = true; //夠上了return { ...item };});} else {//不符合要求的話,就忽略傳入的已選中元素this.selectedItems = [];}//初始化列表查詢數據this.form.pageNum = 1;//查詢列表數據this.getList();
}
getList函數
- 獲取元素時候,給【服務器返回的數據list】做勾選初始化
- 這里就處理了點擊上下頁面和第一次加載時候可以鉤上已選數據
//獲取元素時候,給【服務器返回的數據list】做勾選初始化
//這里就處理了點擊上下頁面和第一次加載時候可以鉤上已選數據
function getlList() {//合并請求參數listAJAXFN({ ...this.form, ...this.params }).then((res) => {if (res.code == 200) {let { rows, total, size } = res.data;// 創建選中序列號的Set,用于O(1)快速查找//數組轉set,方便快速判斷const selectArrSet = new Set(this.pickedArr.map((item) => item.id));// 在單次迭代中處理所有行rows = rows.map((item) => {//如果已選元素里有這個元素,就鉤上item.checked = selectArrSet.has(item.id);return item;});this.list = rows.filter((item) => !this.filterids.includes(item.id));}});
}
同步函數
- 1.把本頁勾選了的數據給外面傳入已勾選的數據對應勾選上
- 2.把本頁存在且勾選了,但是外層傳入的數組里面沒有元素找出來合并到已選數據上面
- 3.全選或者單個勾選(取消或者夠上)時候調用就可以了
//更新已選擇的序列號
//在勾選過程中
function updateselectedSerialNumWhenPick() {//步驟一//判斷有沒有勾選上,針對外面已有選中數據// 合并checked屬性到this.pickedArr中存在的元素this.pickedArr.forEach((aItem) => {//從本頁勾選的數組中找到外層傳入的勾選數據進行匹配//如果存在就給他勾選(因為進入頁面后,用戶可能取消掉了也有可能)//這里只勾選就好了,不需要管不勾選的,不勾選的也不是我們想要的const matchingBItem = this.list.find((bItem) => bItem.id === aItem.id);if (matchingBItem) {aItem.checked = matchingBItem.checked;}});//步驟二,針對本頁勾選的,但是外層數據沒有傳入的數據,//要把它們找出來,并合并到一選數組里面// 獲取當前頁面中中有而a中沒有的元素//夠上了,且外面已勾選的沒有它的數組const uniqueToB = this.list.filter((item) => item.checked).filter((bItem) => !this.pickedArr.some((aItem) => aItem.id === bItem.id));//更新已選中數據this.pickedArr = [...this.pickedArr, ...uniqueToB];
}
確認函數
把已選好的數組里面的checked過濾下,傳遞出去,外面直接接收就行了
onMulitComfirm() {//從已選元素里面拿const arr =this.pickedArr.filter((item) => item.checked);if (arr.length == 0) {this.$u.toast('請勾選序列號');return;}this.$emit('choose', this.material, arr);this.showMaterialPopup = false;
}