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 集合来标记哪些行正在加载中。这样可以更好地控制在某些条件下禁止选择或在加载中时保持选择状态。

实现效果

跨页保存

禁选某些状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/236337.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF绘制进度条(弧形,圆形,异形)

前言 WPF里面圆形进度条实现还比较麻烦,主要涉及到的就是动态绘制进度条的进度需要用到简单的数学算法。其实原理比较简单,我们需要的是话两条重叠的弧线,里面的弧线要比里面的弧线要宽,这样简单的雏形就出来了。 基础写法 我们可以用Path来绘制弧线,代码如下: <Gr…

vue中.sync修饰符与$emit(update:xxx)双向数据绑定

文章目录 一、单向数据流二、props父子传值2.1、父组件2.2、子组件2.3、优缺点2.3.1、优点2.3.2、缺点 三、.sync修饰符双向绑定3.1、父组件3.2、子组件3.3、优缺点3.3.1、优点3.3.2、缺点 3.4、[文档](https://v2.cn.vuejs.org/v2/guide/components-custom-events.html#sync-%…

(Ant X6)子组件里的流程图画布无法显示

(Ant X6)子组件里的流程图画布无法显示 问题背景&#xff1a;侧导航页面都是子组件,建模页面的画布无法显示 解决前&#xff1a; 解决后&#xff1a; 解决思路&#xff1a;点击建模菜单时再次加载对应组件 在 Vue 中&#xff0c;每个组件都有一个唯一的 key 属性。当组件的 ke…

HTML-标签之文字排版、图片、链接、音视频

1、标签语法 HTML超文本标记语言——HyperText Markup Language 超文本是链接标记也叫标签&#xff0c;带尖括号的文本 2、HTML基本骨架 HTML基本骨架是网页模板 html&#xff1a;整个网页head&#xff1a;网页头部&#xff0c;存放给浏览器看的代码&#xff0c;例如CSSbody…

【智能家居】二、添加火灾检测模块(烟雾报警功能点)

可燃气体传感器 MQ-2 和 蜂鸣器 代码段 controlDevice.h&#xff08;设备控制&#xff09;smokeAlarm.c&#xff08;烟雾报警器&#xff09;buzzer.c&#xff08;蜂鸣器&#xff09;mainPro.c&#xff08;主函数&#xff09;运行结果 可燃气体传感器 MQ-2 和 蜂鸣器 代码段 …

Linux基础操作二:Linux系统介绍

1、系统启动过程 Linux系统的启动过程并不是大家想象中的那么复杂&#xff0c;其过程可以分为5个阶段&#xff1a; 内核的引导。运行 init。系统初始化。建立终端 。用户登录系统。 1.1、内核引导 当计算机打开电源后&#xff0c;首先是BIOS开机自检&#xff0c;按照BIOS中…

Ruoyi-Vue或者Ruoyi-Cloud登录进去之后的第一个页面如何修改(即如何去掉首页或者如何修改首页)

其实大家如果看过最近的码云上的issues 就能知道这个问题的答案了。 我这里给出一下链接&#xff1a;https://gitee.com/y_project/RuoYi-Vue/issues/I60JIY 开始 第一步&#xff0c;把router/index.js里面关于首页的路由给注释掉或者删除掉&#xff0c;如图&#xff1a; 第…

Vue大屏自适应终极解决方案

v-scale-screenv-scale-screen是一个大屏自适应组件&#xff0c;在实际业务中&#xff0c;我们常用图表来做数据统计&#xff0c;数据展示&#xff0c;数据可视化等比较直观的方式来达到一目了然的数据查看&#xff0c;但在大屏开发过程中&#xff0c;常会因为适配不同屏幕而感…

亚马逊云科技re:Invent Peter DeSantis演讲,数据规模拓展无极限引领Serverless构建之路

re:lnvent 2023 Peter DeSantis主题演讲&#xff0c;数据规模拓展无极限引领Serverless构建之路&#xff08;Road to Serverless&#xff09;。 Logical Qubit全新发布&#xff1a;量子计算硬件&#xff0c;6倍的量子纠错效率提升。 Amazon全新发布Redshift Serverless&#xf…

kubernetes(k8s)容器内无法连接同所绑定的Service ClusterIP问题记录

kubernetes(k8s)容器内无法连接同所绑定的Service ClusterIP问题记录 1. k8s环境 k8s使用kubernetes-server-linux-amd64_1.19.10.tar.gz 二进制bin 的方式手动部署 k8s 版本: [rootmaster ~]# kubectl version Client Version: version.Info{Major:"1", Minor:&…

java-Swing界面简析

一、简析&#xff1a; 调用java提供的 java.swing包下的各种类可以实现界面中的各种组件(比如输入框、密码框按钮、单选框、复选框等) 二、java.swing包的关键类&#xff1a; 顶层容器&#xff1a;Jframe(窗口) 中间容器&#xff1a;Jpanel(面板) 基本控件&#xff1a; I…

(一)C语言概述

文章目录 一、C语言1、计算机结构组成 二、第一个C语言程序&#xff1a;hello world1、编写C语言代码&#xff1a;hello.c2、通过gcc编译C代码&#xff08;1&#xff09;gcc编译器介绍&#xff08;2&#xff09;Window平台中gcc环境配置 3、代码分析&#xff08;1&#xff09;#…