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
取消全选
- 覆盖全部选择相关事件:
代码示例
模板部分
html
<template>
<div class="container">
<Table
border
ref="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>
脚本部分
javascript
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" |
用于获取表格实例操作选中状态 |
状态同步流程
PageComponent Table StateStore UI 加载新数据 触发数据更新 获取已选数据 同步选中状态 更新勾选显示 PageComponent Table StateStore UI
性能优化策略
-
使用 Set 结构加速查找
javascriptconst idSet = new Set(currentPageIds); this.selectedHospitals.filter(item => !idSet.has(item.id));
-
批量操作减少 DOM 操作
javascriptthis.$nextTick(() => { this.syncSelectionStates(); });
-
防重复处理
javascriptselection.filter(row => !this.selectedHospitals.some( item => item.id === row.HOSPITAL_ID ) )
注意事项
-
数据一致性
- 确保接口返回数据包含
HOSPITAL_ID
字段 - 分页大小(pageSize)需前后端统一
- 确保接口返回数据包含
-
性能限制
- 推荐在选中数据量 < 1000 时使用前端方案
- 超过 1000 条建议改用服务端存储方案
-
特殊场景处理
javascript// 清空所有选择 clearAllSelections() { this.selectedHospitals = []; this.$refs.selection.selectAll(false); }
-
版本兼容性
- 需要 iView 4.3+ 版本支持完善的行选择功能
扩展功能建议
1. 选中项展示面板
html
<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. 服务端全选方案
javascript
handleSelectAllPages() {
this.$Modal.confirm({
title: '全选确认',
content: '将选择全部符合条件的记录(共'+this.totalCount+'条)',
onOk: async () => {
const res = await api.selectAllHospitalIds();
this.selectedHospitals = res.data.map(id => ({
id,
name: '需二次加载名称'
}));
}
});
}
3. 本地持久化存储
javascript
// 在 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: 全选操作性能较差
✅ 优化建议:
javascript
// 使用 Web Worker 处理大数据
const worker = new Worker('./selectionWorker.js');
worker.postMessage({ data: bigData });
Q3: 需要兼容多表格共存场景
✅ 改进方案:
javascript
// 使用 Symbol 作为存储键
const STORAGE_KEY = Symbol('hospital_selection');
this[STORAGE_KEY] = selectedData;