iView Table 组件跨页选择功能实现文档
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;