iView Table 组件跨页选择功能实现文档

iView Table 组件跨页选择功能实现文档

功能概述

实现基于 iView Table 组件的多选功能,支持以下特性:

  • ✅ 跨页数据持久化选择
  • ✅ 当前页全选/取消全选
  • ✅ 自动同步选中状态显示
  • ✅ 分页切换状态保持
  • ✅ 高性能大数据量支持

实现方案

技术栈

  • iView UI 4.x
  • Vue.js 2.x

核心思路

  1. 状态存储

    • 使用独立数组 selectedHospitals 存储选中项
    • 以唯一标识符 HOSPITAL_ID 作为数据标识
  2. 状态同步

    • 分页加载后同步表格选中状态
    • 使用 row-key 保证行识别稳定性
  3. 事件处理

    • 覆盖全部选择相关事件:
      • @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

性能优化策略

  1. 使用 Set 结构加速查找

    javascript 复制代码
    const idSet = new Set(currentPageIds);
    this.selectedHospitals.filter(item => !idSet.has(item.id));
  2. 批量操作减少 DOM 操作

    javascript 复制代码
    this.$nextTick(() => {
      this.syncSelectionStates();
    });
  3. 防重复处理

    javascript 复制代码
    selection.filter(row => 
      !this.selectedHospitals.some(
        item => item.id === row.HOSPITAL_ID
      )
    )

注意事项

  1. 数据一致性

    • 确保接口返回数据包含 HOSPITAL_ID 字段
    • 分页大小(pageSize)需前后端统一
  2. 性能限制

    • 推荐在选中数据量 < 1000 时使用前端方案
    • 超过 1000 条建议改用服务端存储方案
  3. 特殊场景处理

    javascript 复制代码
    // 清空所有选择
    clearAllSelections() {
      this.selectedHospitals = [];
      this.$refs.selection.selectAll(false);
    }
  4. 版本兼容性

    • 需要 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: 切换分页后选中状态显示异常

✅ 解决方案:

  1. 检查是否设置 row-key
  2. 确认在数据更新后调用 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;

相关推荐
lyz2468595 小时前
iview表单提交验证时,出现空值参数被过滤掉不提交的问题解决
view design
zzlyx992 个月前
设备管理系统功能与.NET+VUE(IVIEW)技术实现
前端·vue.js·view design
lyz2468592 个月前
iview table组件中修改按钮时 要注意是否真的修改了值
view design
花伤情犹在2 个月前
uView UI 在 UniApp 中的集成与配置
uni-app·view design
小茗同学阿4 个月前
如何实现分片上传功能:基于 Vue 和 iView 上传组件的详细教程
前端·vue.js·view design
初遇你时动了情5 个月前
解决uview ui赋值后表单无法通过验证
view design
Э时间行者于我5 个月前
iview upload clearFiles清除回显视图
前端·view design
行思理5 个月前
iView-admin2.0 新手教程(一)
macos·node.js·view design·iview admin
代码老祖5 个月前
vue3+view-ui-plus+vite+less 实现自定义iview样式
前端·ui·vue3·vite·view design