Element UI 实战:跨页保存表格选中状态与判断状态可选性的高效方案

本文主要是介绍Element UI 实战:跨页保存表格选中状态与判断状态可选性的高效方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

        在前文中,我们曾深入探讨了在修改数据后跨页时提醒用户可能丢失数据的问题。虽然这种方式对于一些场景是足够的,但当涉及选择框时,我们需要更为智能和高效的解决方案。在本文中,我们将分享一种基于 Element UI 的实际案例,旨在实现跨页保存选中项与禁选特定项的需求。通过以下详细讨论,你将了解到这一方案的实现原理及其用户体验效果。

问题背景

        在许多 Web 应用中,数据分页是常见的操作方式。当用户在一个页面中选择了一些数据项,然后切换到另一页时,保持之前选中的项通常是用户友好的体验。同时,可能存在一些需要禁选的执行项,例如在某些状态下,用户不应该选择或执行某些操作:如当数据可以进行执行相关操作,并且需要消耗一定时间时,我们为了任务的完整执行,会在任务执行期间,禁止选中该任务的选择框(可以预防用户进行删除等操作),后续执行完毕可以恢复初始选中状态,也可以放弃选中状态。

方案设计与实现

        在 Element UI 中,表格(Table)组件提供了丰富的特性和事件。可以利用这些特性和事件来实现跨页保存选中项和禁选执行项的需求。

实现

        1.跨页保存

        在许多 Web 应用中,数据分页是常见的操作方式。当用户在一个页面中选择了一些数据项,然后切换到另一页时,保持之前选中的项通常是用户友好的体验。

        模板
    <el-tableref="multipleTable":data="tableData"@select="handleSelectionChange"@select-all="handleSelectionAll"><el-table-column type="selection" align="center"></el-table-column><el-table-column prop="name" label="name" align="center"></el-table-column><el-table-column prop="age" label="age" align="center"></el-table-column></el-table><el-pagination:background="true":current-page.sync="queryParams.page":page-size.sync="queryParams.pageSize"layout="total,prev,pager,next,sizes":total="total":page-sizes="[5, 10, 20, 40]"@size-change="getList"@current-change="getList" />
        脚本
data() {return {total: void 0,queryParams: {page: 1,pageSize: 10,},allData: [],tableData: [],multipleSelection: [],listId: [],};},mounted() {this.getList();},methods: {getList() {this.allData = [{ name: 'A', age: 1 },{ name: 'B', age: 2 },{ name: 'C', age: 3 },{ name: 'D', age: 4 },{ name: 'E', age: 5 },{ name: 'F', age: 6 },{ name: 'G', age: 7 },{ name: 'H', age: 8 },{ name: 'I', age: 9 },{ name: 'J', age: 10 },{ name: 'K', age: 11 },{ name: 'L', age: 12 },{ name: 'M', age: 13 },{ name: 'N', age: 14 },{ name: 'O', age: 15 },{ name: 'P', age: 16 },{ name: 'Q', age: 17 },{ name: 'R', age: 18 },{ name: 'S', age: 19 },{ name: 'T', age: 20 },{ name: 'U', age: 21 },{ name: 'V', age: 22 },{ name: 'W', age: 23 },{ name: 'X', age: 24 },{ name: 'Y', age: 25 },{ name: 'Z', age: 26 },];this.total = this.allData.length;let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;let currentPageSize = this.queryParams.pageSize - 1 || 1;this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize + 1);this.listId = [];this.tableData.forEach(item => this.listId.push(item.name));this.$nextTick(() => {this.tableData.forEach((item, index) => {if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);}});});},// 全选handleSelectionAll(val) {if (val.length) {const result = [];this.listId.forEach(id => {if (this.multipleSelection.every(item => item !== id)) result.push(id);});this.multipleSelection.push(...result);} else {this.listId.forEach(id => {this.multipleSelection = this.multipleSelection.filter(item => item !== id);});}},// 单选handleSelectionChange(rows, row) {if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 过滤(删除)else this.multipleSelection.push(row.name);},
}
        解析
  1. getList 方法:

    • 发送 HTTP GET 请求,获取数据(/.../是请求的地址,queryParams是请求参数)。
    • 在请求成功的回调中,判断返回数据的状态是否为200,如果是,将返回的数据赋值给 tableData
    • 构建 listId 数组,存储 tableData 中每一项的 id
    • 利用 $nextTick,确保在 Vue 更新 DOM 后执行,遍历 tableData,对于已经在 multipleSelection 中的项,在表格中选中对应的行。
  2. handleSelectionAll 方法:

    • 接受一个参数 val,即当前页选中的所有行数据。
    • 如果 val.length 大于 0,表示当前页有选中的行,遍历 listId,将不在 multipleSelection 中的项添加到 multipleSelection 中。
    • 如果 val.length 为 0,表示当前页没有选中的行,遍历 listId,将在 multipleSelection 中的项从中移除。
  3. handleSelectionChange 方法:

    • 接受两个参数,rows 是当前页选中的所有行数据,row 是当前操作的行数据。
    • 如果 multipleSelection 中已经存在 row.id,则将其从 multipleSelection 中移除,否则将其添加到 multipleSelection 中。

        这些方法共同实现了跨页保存选中状态的功能,通过维护 multipleSelection 数组来保存用户选择的行的 id,从而在表格分页切换时保持选中状态。

        2.禁选执行项

        数据拥有执行状态之类的字段,并且需要消耗一定时间时,我们为了任务的完整执行,会在任务执行期间,禁止选中该任务的选择框(以避免删除等操作)。执行完毕后可以恢复初始选中状态,也可以放弃选中状态。

         以下代码选择的是后者,即在重新开始运行时,禁用该项选择框并且执行完毕后不重新选中。如果希望保留,在对应执行的函数(下述为 reloadTask)中不删除 multipleSelection 中对应的id即可。

        模板
    <el-tableref="multipleTable":data="tableData"@select="handleSelectionChange"@select-all="handleSelectionAll"><el-table-column type="selection" align="center" :selectable="selectable"></el-table-column><el-table-column prop="name" label="name" align="center"></el-table-column><el-table-column prop="age" label="age" align="center"></el-table-column><el-table-column label="status"><template slot-scope="scope"><spanstyle="margin-right:10px; cursor: pointer;":class="scope.row.status !== '执行中' ? 'el-icon-caret-right' : 'el-icon-loading'"size="small":disabled="scope.row.status === '执行中'"@click="reloadTask(scope.row)"></span><el-tag :type="scope.row.status !== '执行中' ? '' : 'info'">{{scope.row.status}}</el-tag></template></el-table-column></el-table><el-pagination:background="true":current-page.sync="queryParams.page":page-size.sync="queryParams.pageSize"layout="total,prev,pager,next,sizes":total="total":page-sizes="[5, 10, 20, 40]"@size-change="getList"@current-change="getList" />
        脚本
data() {return {total: void 0,queryParams: {page: 1,pageSize: 10,},allData: [],tableData: [],multipleSelection: [],listId: [],loadingSelection: new Set(),};},mounted() {this.getList();},methods: {getList(flag = false) {if (!flag) {this.allData = [{ name: 'A', age: 1, status: '执行完毕' },{ name: 'B', age: 2, status: '执行中' },{ name: 'C', age: 3, status: '执行完毕' },{ name: 'D', age: 4, status: '未执行' },{ name: 'E', age: 5, status: '未执行' },{ name: 'F', age: 6, status: '执行中' },{ name: 'G', age: 7, status: '执行中' },{ name: 'H', age: 8, status: '执行中' },{ name: 'I', age: 9, status: '执行中' },{ name: 'J', age: 10, status: '未执行' },{ name: 'K', age: 11, status: '未执行' },{ name: 'L', age: 12, status: '未执行' },{ name: 'M', age: 13, status: '未执行' },{ name: 'N', age: 14, status: '未执行' },{ name: 'O', age: 15, status: '未执行' },{ name: 'P', age: 16, status: '未执行' },{ name: 'Q', age: 17, status: '未执行' },{ name: 'R', age: 18, status: '未执行' },{ name: 'S', age: 19, status: '未执行' },{ name: 'T', age: 20, status: '未执行' },{ name: 'U', age: 21, status: '未执行' },{ name: 'V', age: 22, status: '未执行' },{ name: 'W', age: 23, status: '未执行' },{ name: 'X', age: 24, status: '未执行' },{ name: 'Y', age: 25, status: '未执行' },{ name: 'Z', age: 26, status: '未执行' },];}this.total = this.allData.length;let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;let currentPageSize = this.queryParams.pageSize - 1 || 1;this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize + 1);this.listId = [];this.tableData.forEach(item => this.listId.push(item.name));this.$nextTick(() => {this.tableData.forEach((item, index) => {if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);}});});},// 执行任务reloadTask(row) {this.multipleSelection = this.multipleSelection.filter(item => item !== row.name);row.status = '执行中';this.getList(true);},// 判断可选性selectable(row) {if (row.status !== '执行中') {if (this.loadingSelection.has(row.name)) this.loadingSelection.delete(row.name);return true;} else {this.loadingSelection.add(row.name);return false;}},// 全选handleSelectionAll(val) {if (val.length) {const result = [];this.listId.forEach(id => {if (this.multipleSelection.every(item => item !== id) && !this.loadingSelection.has(id)) result.push(id);});this.multipleSelection.push(...result);} else {this.listId.forEach(id => {this.multipleSelection = this.multipleSelection.filter(item => item !== id);});}},// 单选handleSelectionChange(rows, row) {if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 过滤(删除)else this.multipleSelection.push(row.name);},},
         解析

        这部分代码经过修改后主要涉及到对行的可选性(selectable 方法)以及全选处理(handleSelectionAll 方法)。下面是对修改部分代码的详细解释:

  1. selectable 方法:

    • selectable 方法用于确定给定行 row 是否可选。如果行的状态 status 不是 '执行中',则认为该行可选。
    • 如果行不可选,而且 loadingSelection 集合中已经存在该行的 id,则将其从 loadingSelection 中删除,表示加载完成。
    • 如果行可选,将其 id 添加到 loadingSelection 集合中,表示正在加载中,并返回 false 表示不可选;否则,返回 true 表示可选。
  2. handleSelectionAll 方法:

    • 该方法用于处理全选操作。接收参数 val,即当前页选中的所有行数据。
    • 如果有选中的行,遍历 listId,将不在 multipleSelection 中且不在 loadingSelection 中的项添加到 multipleSelection 中。
    • 如果没有选中的行,遍历 listId,将在 multipleSelection 中的项从中移除。

        这些修改主要增加了对行的可选性的判断,以及对加载状态的管理,通过 loadingSelection 集合来标记哪些行正在加载中。这样可以更好地控制在某些条件下禁止选择或在加载中时保持选择状态。

实现效果

跨页保存

禁选某些状态

这篇关于Element UI 实战:跨页保存表格选中状态与判断状态可选性的高效方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/441472

相关文章

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Java MQTT实战应用

《JavaMQTT实战应用》本文详解MQTT协议,涵盖其发布/订阅机制、低功耗高效特性、三种服务质量等级(QoS0/1/2),以及客户端、代理、主题的核心概念,最后提供Linux部署教程、Sprin... 目录一、MQTT协议二、MQTT优点三、三种服务质量等级四、客户端、代理、主题1. 客户端(Clien

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(