iView Table 組件跨頁選擇功能實現文檔
功能概述
實現基于 iView Table 組件的多選功能,支持以下特性:
- ? 跨頁數據持久化選擇
- ? 當前頁全選/取消全選
- ? 自動同步選中狀態顯示
- ? 分頁切換狀態保持
- ? 高性能大數據量支持
實現方案
技術棧
- iView UI 4.x
- Vue.js 2.x
核心思路
-
狀態存儲
- 使用獨立數組
selectedHospitals
存儲選中項 - 以唯一標識符
HOSPITAL_ID
作為數據標識
- 使用獨立數組
-
狀態同步
- 分頁加載后同步表格選中狀態
- 使用
row-key
保證行識別穩定性
-
事件處理
- 覆蓋全部選擇相關事件:
@on-select
單個選擇@on-select-all
全選當前頁@on-select-cancel
取消單個@on-select-all-cancel
取消全選
- 覆蓋全部選擇相關事件:
代碼示例
模板部分
<template><div class="container"><Tableborderref="selection"row-key="HOSPITAL_ID":columns="columns":data="currentPageData"@on-select="handleSelect"@on-select-all="handleSelectAll"@on-select-cancel="onSelectCancel"@on-select-all-cancel="onSelectAllCancel"/><Page:total="totalCount":current="currentPage"@on-change="handlePageChange"show-total/></div>
</template>
腳本部分
export default {data() {return {// 表格配置columns: [{ type: 'selection',width: 60,align: 'center',fixed: 'left'},// 其他數據列...],// 核心數據currentPageData: [],selectedHospitals: [],currentPage: 1,totalCount: 0}},methods: {// 數據獲取方法async loadPageData(page = 1) {const res = await api.getHospitalList({page,pageSize: 10});this.currentPageData = res.data.items;this.totalCount = res.data.total;this.currentPage = page;this.$nextTick(this.syncSelectionStates);},// 狀態同步方法syncSelectionStates() {this.currentPageData.forEach((row, index) => {const isSelected = this.selectedHospitals.some(item => item.id === row.HOSPITAL_ID);if (isSelected) {this.$refs.selection.toggleSelect(index);}});},// 事件處理handleSelect(_, row) {const targetIndex = this.selectedHospitals.findIndex(item => item.id === row.HOSPITAL_ID);if (targetIndex === -1) {this.selectedHospitals.push({id: row.HOSPITAL_ID,name: row.NAME,// 可擴展其他需要保存的字段});} else {this.selectedHospitals.splice(targetIndex, 1);}},handleSelectAll(selection) {if (selection.length === 0) {this.handleDeselectCurrentPage();} else {this.handleSelectCurrentPage(selection);}},handleSelectCurrentPage(selection) {const newSelections = selection.filter(row => !this.selectedHospitals.some(item => item.id === row.HOSPITAL_ID)).map(row => ({id: row.HOSPITAL_ID,name: row.NAME}));this.selectedHospitals.push(...newSelections);},handleDeselectCurrentPage() {const currentPageIds = new Set(this.currentPageData.map(row => row.HOSPITAL_ID));this.selectedHospitals = this.selectedHospitals.filter(item => !currentPageIds.has(item.id));}}
}
核心邏輯說明
關鍵配置
配置項 | 說明 |
---|---|
row-key | 必須設置為數據唯一標識字段 |
ref="selection" | 用于獲取表格實例操作選中狀態 |
狀態同步流程
性能優化策略
-
使用 Set 結構加速查找
const idSet = new Set(currentPageIds); this.selectedHospitals.filter(item => !idSet.has(item.id));
-
批量操作減少 DOM 操作
this.$nextTick(() => {this.syncSelectionStates(); });
-
防重復處理
selection.filter(row => !this.selectedHospitals.some(item => item.id === row.HOSPITAL_ID) )
注意事項
-
數據一致性
- 確保接口返回數據包含
HOSPITAL_ID
字段 - 分頁大小(pageSize)需前后端統一
- 確保接口返回數據包含
-
性能限制
- 推薦在選中數據量 < 1000 時使用前端方案
- 超過 1000 條建議改用服務端存儲方案
-
特殊場景處理
// 清空所有選擇 clearAllSelections() {this.selectedHospitals = [];this.$refs.selection.selectAll(false); }
-
版本兼容性
- 需要 iView 4.3+ 版本支持完善的行選擇功能
擴展功能建議
1. 選中項展示面板
<template><div class="selected-panel"><Tag v-for="item in selectedHospitals" :key="item.id"closable@on-close="handleRemoveTag(item.id)">{{ item.name }}</Tag></div>
</template>
2. 服務端全選方案
handleSelectAllPages() {this.$Modal.confirm({title: '全選確認',content: '將選擇全部符合條件的記錄(共'+this.totalCount+'條)',onOk: async () => {const res = await api.selectAllHospitalIds();this.selectedHospitals = res.data.map(id => ({id,name: '需二次加載名稱' }));}});
}
3. 本地持久化存儲
// 在 created 鉤子中
const saved = localStorage.getItem('selectedHospitals');
if (saved) {this.selectedHospitals = JSON.parse(saved);
}// 添加 watch
watch: {selectedHospitals: {deep: true,handler(newVal) {localStorage.setItem('selectedHospitals', JSON.stringify(newVal));}}
}
常見問題
Q1: 切換分頁后選中狀態顯示異常
? 解決方案:
- 檢查是否設置
row-key
- 確認在數據更新后調用
syncSelectionStates
Q2: 全選操作性能較差
? 優化建議:
// 使用 Web Worker 處理大數據
const worker = new Worker('./selectionWorker.js');
worker.postMessage({ data: bigData });
Q3: 需要兼容多表格共存場景
? 改進方案:
// 使用 Symbol 作為存儲鍵
const STORAGE_KEY = Symbol('hospital_selection');
this[STORAGE_KEY] = selectedData;