【vue组件】使用element-ui table 实现嵌套表格 点击展开时获取数据

应用场景是这样
主表格的数据是所有的学校
然后点击展开的时候,获取学校下相应班级的数据
并且班级要能选择后生成图表,但所有的班级最多选择5个

首先是嵌套表格

<div><el-table:data="tableDisplayData"id="chartTableExpand"style="width: 100%"ref="chartTable"@expand-change="handleRowClick":expand-row-keys="expandedRows":row-key="getRowKeys"><el-table-column type="expand"><template slot-scope="scope"><el-table:ref="'expandTable' + scope.row.id":data="scope.row.tableExpandData"style="width: 100%"v-loading="expandLoading"@selection-change="(val) => {return handleExpandSelectionChange(val, scope.row.id);}"><el-table-column:selectable="(row) => {return checkSelectable(row, 'id');}"type="selection"></el-table-column><el-table-columnprop="className"label="班级名称"width="180"fixed="left"><template slot-scope="scope"><span>{{ scope.row.Name }}</span></template></el-table-column><el-table-column prop="studentCount" label="学生数量"><template slot-scope="scope"><span>{{ scope.row.StudentCount }}</span></template></el-table-column><el-table-column prop="answerCount" label="回答数量"><template slot-scope="scope"><span>{{ scope.row.AnswerCount }}</span></template></el-table-column></el-table></template></el-table-column><el-table-column prop="schoolName" label="学校名"><template slot-scope="scope"><span>{{ scope.row.schoolName }}</span></template></el-table-column><el-table-column prop="classCount" label="班级数量"><template slot-scope="scope"><span>{{ scope.row.classCount }}</span></template></el-table-column><el-table-column prop="status" label="时间"><template slot-scope="scope"><span>{{ scope.row.date }}</span></template></el-table-column><el-table-column prop="search"><template slot="header" slot-scope="scope"><el-input v-model="searchKey" size="medium" placeholder="Search" /></template><template slot-scope="scope"> </template></el-table-column></el-table></div>

在主表格type为expand的行(<el-table-column type="expand">)下面添加子表格,并且添加方法

@selection-change="(val) => {return handleExpandSelectionChange(val, scope.row.id); }"

传入主表格row的数据和row的id

在方法handleExpandSelectionChange中,将 multipleSelection的值对应相应的table存起来,也就是说一个table 对应它自己的 multipleSelection,键是tableId ;值是每个table自己的multipleSelection,这样能解决多个table共用一个multipleSelection时会出现前一个子table选中的值会被后一个子table选中的值替换掉的问题

handleExpandSelectionChange(val, tableId) {let _this = this;// 如果是表格展开时去点击的话,就不要改变selections的值if (!_this.isClassTableExpanded) {// 这里将 multipleSelection的值对应相应的table存起来// 也就是说一个table 对应它自己的 multipleSelection// 键是tableId 值是 multipleSelection_this.selections[tableId] = val;}_this.updateMultipleSelection();},

在方法updateMultipleSelection中,会将各个表格的multipleSelection汇总,形成一个总的multipleSelection,再根据这个汇总的multipleSelection进行后面的处理

updateMultipleSelection() {let _this = this;// 把selections里的row取出来汇总_this.multipleSelection = [].concat.apply([],Object.keys(_this.selections).map(function (key) {return _this.selections[key];}));// 用汇总后的multipleSelection来生成图表},

然后再看主表格的展开时触发的方法

@expand-change="handleRowClick"

在handleRowClick方法中
通过方法getExpandClassData中获取数据

	// 点击展开handleRowClick(row,rows) {let _this = this;_this.getExpandClassData(row,rows);},// 获取学校或班级汇总数据async getExpandClassData(row,rows) {let _this = this;let schoolId = row.id// 展开class table对应的reflet expandTable = "expandTable" + schoolId;// table展开时,根据之前选中的选项通过toggleRowSelection点击checkbox_this.$nextTick(function () {if (_this.$refs[expandTable]) {let hasSelections =_this.selections.length > 0 ||_this.selections[schoolId] ||(_this.selections[schoolId]? _this.selections[schoolId].length: undefined) > 0;if (hasSelections) {_this.isClassTableExpanded = true;let selectedIds = _this.selections[schoolId].map((mSelect) => mSelect.id);row.tableExpandData.forEach((row) => {if (selectedIds.includes(row.id)) {_this.$refs[expandTable].toggleRowSelection(row, true);}});}}_this.isClassTableExpanded = false;});const delIndex = _this.expandedRows.findIndex((item)=>{return item === schoolId});if (delIndex > -1) {_this.expandedRows.splice(delIndex, 1);}const isRowNowExpand = rows.some(r => r.id === row.id) // 判断当前行展开状态if (isRowNowExpand) {_this.expandedRows = [schoolId,..._this.expandedRows];}// 如果已经展开获取或数据了,就返回不要再获取了if (row.isExpanded) {return;}_this.expandLoading = true;await _this.getClassList(row.id);// 将school下对应的class表格数据,赋值到相应的school下// 作为tableExpandData存起来_this.$nextTick(() => {_this.$set(row, "tableExpandData", _this.tableExpandData);_this.$set(row, "isExpanded", true);_this.expandLoading = false;});},

注意在上面代码中
通过await _this.getClassList(row.id);获取到班级数据
然后将数据赋值给对应的row

_this.$nextTick(() => {_this.$set(row, "tableExpandData", _this.tableExpandData);_this.$set(row, "isExpanded", true);_this.expandLoading = false;});

但这里会产生一个问题,用$set赋值后,页面会重新渲染,展开的table会收回去,我的想法是让展开的table保持展开的状态,
这里使用到的就是:expand-row-keys="expandedRows"

首先在主表格中添加

<el-table...:expand-row-keys="expandedRows":row-key="getRowKeys">

注意一定要设置row-key
然后在下面代码里

const delIndex = _this.expandedRows.findIndex((item)=>{return item === schoolId});
if (delIndex > -1) {_this.expandedRows.splice(delIndex, 1);
}const isRowNowExpand = rows.some(r => r.id === row.id) // 判断当前行展开状态
if (isRowNowExpand) {_this.expandedRows = [schoolId,..._this.expandedRows];
}

首先要将_this.expandedRows中对应主表展开行的数据清除掉
然后通过const isRowNowExpand = rows.some(r => r.id === row.id)判断当前行是否展开
如果展开就把当前行添加到expandedRows 中,那样页面刷新后会保持展开状态

在getExpandClassData这个方法里还要注意的是
首先对展开的子table设置对应的ref

let expandTable = "expandTable" + schoolId;

然后,因为选中子table的单选框后,把展开的子table收齐再展开时,单选框的选中样式会丢失,这时我想的办法是根据之前选中的选项,调用toggleRowSelection这个方法,再把单选框选中

// table展开时,根据之前选中的选项通过toggleRowSelection点击checkbox_this.$nextTick(function () {if (_this.$refs[expandTable]) {let hasSelections =_this.selections.length > 0 ||_this.selections[schoolId] ||(_this.selections[schoolId]? _this.selections[schoolId].length: undefined) > 0;if (hasSelections) {_this.isClassTableExpanded = true;let selectedIds = _this.selections[schoolId].map((mSelect) => mSelect.id);row.tableExpandData.forEach((row) => {if (selectedIds.includes(row.id)) {_this.$refs[expandTable].toggleRowSelection(row, true);}});}}_this.isClassTableExpanded = false;});

在上面代码中hasSelections 是判断是否有选中的选项,然后把展开子表格选中的id取出来,根据选中的id调用toggleRowSelection去点击

然后如果已经展开获取过数据了,就返回不要再调用接口获取了

  if (row.isExpanded) {return;}

最后要限制选中的数量,就通过下面的方法
在展开的子表格中单选框对应的行中 添加:selectable

<el-table-column:selectable="(row) => {return checkSelectable(row, 'id'); }"type="selection">

然后checkSelectable方法的实现如下:

// 是否禁用多选
checkSelectable: function (row, key) {let _this = this;let flag = true;// 多选最多选 banNumber 个if (_this.multipleSelection.length >= _this.banNumber) {if (!Array.isArray(row)) {flag = _this.multipleSelection.some((selection) => row[key] === selection[key]);}}return flag;
},

然后通过banNumber 控制限制的数量

最后还有一个搜索方法

 watch: {searchKey: function (val) {this.tableDisplayData = this.filterTableData.filter(function (data) {return data.schoolName.toLowerCase().includes(val.toLowerCase());});},},

完整代码如下:


<template><div><el-table:data="tableDisplayData"id="chartTableExpand"style="width: 100%"ref="chartTable"@expand-change="handleRowClick":expand-row-keys="expandedRows":row-key="getRowKeys"><el-table-column type="expand"><template slot-scope="scope"><el-table:ref="'expandTable' + scope.row.id":data="scope.row.tableExpandData"style="width: 100%"v-loading="expandLoading"@selection-change="(val) => {return handleExpandSelectionChange(val, scope.row.id);}"><el-table-column:selectable="(row) => {return checkSelectable(row, 'id');}"type="selection"></el-table-column><el-table-columnprop="className"label="班级名称"width="180"fixed="left"><template slot-scope="scope"><span>{{ scope.row.Name }}</span></template></el-table-column><el-table-column prop="studentCount" label="学生数量"><template slot-scope="scope"><span>{{ scope.row.StudentCount }}</span></template></el-table-column><el-table-column prop="answerCount" label="回答数量"><template slot-scope="scope"><span>{{ scope.row.AnswerCount }}</span></template></el-table-column></el-table></template></el-table-column><el-table-column prop="schoolName" label="学校名"><template slot-scope="scope"><span>{{ scope.row.schoolName }}</span></template></el-table-column><el-table-column prop="classCount" label="班级数量"><template slot-scope="scope"><span>{{ scope.row.classCount }}</span></template></el-table-column><el-table-column prop="status" label="时间"><template slot-scope="scope"><span>{{ scope.row.date }}</span></template></el-table-column><el-table-column prop="search"><template slot="header" slot-scope="scope"><el-input v-model="searchKey" size="medium" placeholder="Search" /></template><template slot-scope="scope"> </template></el-table-column></el-table></div>
</template><script>
import { getClassData, getSchoolData } from "@/api/api";
export default {name: "embededTable",props: {tooltip: {type: String,default: "",},},data() {return {multipleSelection: [],selections: [],banNumber: 5,isTableSelected: false,tableExpandData: [],filterTableData: [],searchKey: "",tableDisplayData: [],isClassTableExpanded: false,expandedRows: [],expandLoading: false,};},async created() {let _this = this;await _this.getData();},mounted() {let _this = this;},watch: {searchKey: function (val) {this.tableDisplayData = this.filterTableData.filter(function (data) {return data.schoolName.toLowerCase().includes(val.toLowerCase());});},},components: {},methods: {getRowKeys: function (row) {return row.id;},async getClassList(id) {let _this = this;await getClassData(id).then((res) => {_this.tableExpandData = res;}).catch((err) => {console.log(err, "err");});},async getSchoolList() {let _this = this;await getSchoolData().then((res) => {_this.tableData = res;_this.filterTableData = _this.tableData;_this.tableDisplayData = _this.tableData;}).catch((err) => {console.log(err, "err");});},async getData() {let _this = this;await _this.getSchoolList();},// 点击展开handleRowClick(row,rows) {let _this = this;_this.getExpandClassData(row,rows);},// 获取学校或班级汇总数据async getExpandClassData(row,rows) {let _this = this;let schoolId = row.id// 展开class table对应的reflet expandTable = "expandTable" + schoolId;// table展开时,根据之前选中的选项通过toggleRowSelection点击checkbox_this.$nextTick(function () {if (_this.$refs[expandTable]) {let hasSelections =_this.selections.length > 0 ||_this.selections[schoolId] ||(_this.selections[schoolId]? _this.selections[schoolId].length: undefined) > 0;if (hasSelections) {_this.isClassTableExpanded = true;let selectedIds = _this.selections[schoolId].map((mSelect) => mSelect.id);row.tableExpandData.forEach((row) => {if (selectedIds.includes(row.id)) {_this.$refs[expandTable].toggleRowSelection(row, true);}});}}_this.isClassTableExpanded = false;});const delIndex = _this.expandedRows.findIndex((item)=>{return item === schoolId});if (delIndex > -1) {_this.expandedRows.splice(delIndex, 1);}const isRowNowExpand = rows.some(r => r.id === row.id) // 判断当前行展开状态if (isRowNowExpand) {_this.expandedRows = [schoolId,..._this.expandedRows];}console.log(_this.expandedRows)// 如果已经展开获取或数据了,就返回不要再获取了if (row.isExpanded) {return;}_this.expandLoading = true;await _this.getClassList(row.id);// 将school下对应的class表格数据,赋值到相应的school下// 作为tableExpandData存起来// row.tableExpandData = _this.tableExpandData;// row.isExpanded = true;_this.$nextTick(() => {_this.$set(row, "tableExpandData", _this.tableExpandData);_this.$set(row, "isExpanded", true);// _this.expandedRows = [schoolId,..._this.expandedRows];_this.expandLoading = false;});},// 单选handleExpandSelectionChange(val, tableId) {let _this = this;// 如果是表格展开时去点击的话,就不要改变selections的值if (!_this.isClassTableExpanded) {// 这里将 multipleSelection的值对应相应的table存起来// 也就是说一个table 对应它自己的 multipleSelection// 键是tableId 值是 multipleSelection_this.selections[tableId] = val;}_this.updateMultipleSelection();},updateMultipleSelection() {let _this = this;// 把selections里的row取出来汇总_this.multipleSelection = [].concat.apply([],Object.keys(_this.selections).map(function (key) {return _this.selections[key];}));},// 是否禁用多选checkSelectable: function (row, key) {let _this = this;let flag = true;// 多选最多选 banNumber 个if (_this.multipleSelection.length >= _this.banNumber) {if (!Array.isArray(row)) {flag = _this.multipleSelection.some((selection) => row[key] === selection[key]);}}return flag;},},
};
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
/* 去掉全选按钮 */
.el-table__fixed-header-wrapper .el-table__header th .el-checkbox .el-checkbox__input .el-checkbox__inner{display: none;
}
</style>

效果图如下:
在这里插入图片描述

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

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

相关文章

Nacos注册中心

Nacos 安装 https://nacos.io/zh-cn/ 源码安装 第一步&#xff1a;利用Gitee获取nacos在github上的代码到自己的gitee仓库中 https://github.com/alibaba/nacos.git 第二步&#xff1a;下载源码到本地。 第三步&#xff1a;使用maven编译代码。 # 先切换到master分支 gi…

ElasticSearch(ES)简单介绍

ES简介 Elasticsearch&#xff08;通常简称为ES&#xff09;是一个开源的分布式搜索和分析引擎&#xff0c;旨在处理各种类型的数据&#xff0c;包括结构化、半结构化和非结构化数据。它最初是为全文搜索而设计的&#xff0c;但随着时间的推移&#xff0c;它已经演变成一个功能…

JUnit测试进阶(Private测试)

Private测试 前言一、间接调用二、Java反射机制调用 前言 在单元测试中&#xff0c;由于私有方法&#xff08;Private Method&#xff09;无法直接被调用&#xff0c;因此对私有方法进行测试成为一项难题。一个可行的方法是&#xff1a;在测试时将私有方法改变为公有方法&…

【记录】Truenas scale|Truenas 的 SSH 服务连不上 VScode,终端能连上

一般 Truenas连不上 就只有两种情况&#xff1a; 第一种&#xff1a;用户没对应用户目录。需要去用户管理里面对每个用户设置目录。 第二种情况&#xff0c;服务有个选项没勾选。这时会发现能输入密码但是一点反应都没有&#xff0c;打开details会看到报错channel 3: open fai…

nginx配置指南

nginx.conf配置 找到Nginx的安装目录下的nginx.conf文件&#xff0c;该文件负责Nginx的基础功能配置。 配置文件概述 Nginx的主配置文件(conf/nginx.conf)按以下结构组织&#xff1a; 配置块功能描述全局块与Nginx运行相关的全局设置events块与网络连接有关的设置http块代理…

应用程序接口(API)安全的入门指南

本文简单回顾了 API 的发展历史&#xff0c;其基本概念、功能、相关协议、以及使用场景&#xff0c;重点讨论了与之相关的不同安全要素、威胁、认证方法、以及十二项优秀实践。 根据有记录的历史&#xff0c;随着 Salesforce 的销售自动化解决方案的推出&#xff0c;首个 Web…

Learn Prompt-经验法则

还记得我们在“基础用法”当中提到的三个经验法则吗&#xff1f; 尝试提示的多种表述以获得最佳结果使用清晰简短的提示&#xff0c;避免不必要的词语减少不精确的描述 现在经过了几页的学习&#xff0c;我认为是时候引入一些新的原则了。 3. 一个话题对应一个chat​ ChatG…

新一代爬虫工具 katana 配置及使用

新一代爬虫工具 katana 配置及使用。 功能&#xff1a; 快速且完全可配置的网络爬行 标准和无外设模式支持 JavaScript 解析/爬网 可定制的自动表单填写 范围控制 - 预配置字段/正则表达式 可自定义的输出 - 预配置字段 输入 - 标准输入、URL 和列表 输出 - 标准输出、…

常见的数码管中的引脚分布情况

简单介绍 数码管&#xff0c;实际就是用了7段亮的线段表示常见的数字或字符。常见的像下面几种&#xff08;图片是网络中的截图&#xff09;。事件中使用到的知识还是单片机中最基础的矩阵扫描。记得其中重要的有“余晖效应”&#xff0c;好像是要把不用的亮段关闭&#xff0c…

.NET Upgrade Assistant 升级 .NET MAUI

.NET Upgrade Assistant 是一种可帮助您将应用程序升级到最新的 .NET版本 的工具&#xff0c;并且您可以使用这个工具将您的应用程序从旧平台&#xff08;例如 Xamarin Forms 和 UWP&#xff09;迁移到新的平台。此外&#xff0c;这个新版本的工具&#xff0c;可以让您在不更改…

【C++深入浅出】日期类的实现

目录 一. 前言 二. 日期类的框架 三. 日期类的实现 3.1 构造函数 3.2 析构函数 3.3 赋值运算符重载 3.4 关系运算符重载 3.5 日期 /- 天数 3.6 自增与自减运算符重载 3.7 日期 - 日期 四. 完整代码 一. 前言 通过前面两期类和对象的学习&#xff0c;我们已经对C的…

【微信小程序】项目初始化

| var() CSS 函数可以插入一个自定义属性&#xff08;有时也被称为“CSS 变量”&#xff09;的值&#xff0c;用来代替非自定义 属性中值的任何部分。 1.初始化样式与颜色 view,text{box-sizing: border-box; } page{--themColor:#ad905c;--globalColor:#18191b;--focusColor…

RHCSA 重定向、vim练习题

1.重定向练习题 (1)新建一个文件redirect.txt&#xff0c;并在其中写入20210804RHCSA,保存并退出 先输入命令 [rootlocalhost ~]# vim redirect.txt进入vim编辑器后&#xff0c;按快捷键“i”进入编辑模式&#xff0c;再写入数据&#xff0c;写完之后按“esc"键退出编辑…

多款大模型向公众开放,百模大战再升级?

作为一种使用大量文本数据训练的深度学习模型&#xff0c;大模型可以生成自然语言文本或理解语言文本的含义&#xff0c;是通向人工智能的一条重要途径。大模型可以应用于各种机器学习任务&#xff0c;包括自然语言处理、计算机视觉、语音识别、机器翻译、推荐系统、强化学习等…

vue项目通过json-bigint在前端处理java雪花id过长导致失去精度问题

这里 我简单模仿了一个接口 这里 我单纯 返回一个long类型的雪花id 然后 前端 用 axios 去请求 大家知道 axios 会对请求数据做一次处理 而我们 data才是拿到我们java这边实际返回的东西 简单说 就是输出一下我们后端返回 的内容 这里 我们网络中显示的是 35866101868095488…

Mysql树形表的两种查询方案(递归与自连接)

你有没有遇到过这样一种情况&#xff1a; 一张表就实现了一对多的关系&#xff0c;并且表中每一行数据都存在“爷爷-父亲-儿子-…”的联系&#xff0c;这也就是所谓的树形结构 对于这样的表很显然想要通过查询来实现价值绝对是不能只靠select * from table 来实现的&#xff0…

Ubuntu 22.04安装过程

iso下载地址 Ubuntu Releases 1.进入引导菜单 选择Try or Install Ubuntu Server安装 2.选择安装语言 默认选择English 3.选择键盘布局 默认即可 4.选择安装服务器版本 最小化安装 5.配置网络 选择ipv4 选择自定义 DHCP也可 6.配置代理 有需要可以配置 这里跳过 7.软件源 …

Windows配置python(anaconda+vscode方案)的主要步骤及注意事项

Windows配置python&#xff08;anacondavscode方案&#xff09;的主要步骤及注意事项 1、准备工作 anaconda&#xff0c;官网下载&#xff08;直接下载最新版&#xff09;vscode&#xff0c;官网下载 (官网直接下载有可能太慢&#xff0c;可以考虑在国内靠谱的网站上下载&…

第7节-PhotoShop基础课程-视图调整

文章目录 前言1.视图菜单1. 视图操作1.校样颜色 Ctrl Y2.色域警告 Ctrl Shift Y3.像素长宽比 2.显示操作1.大小调整1.Alt 滚轮2.放大选项3.按空格 出现抓手 2.按屏幕大小缩放 Ctrl 0(数字0)3.按实际大小缩放 Ctrl 11.标准屏幕模式2.带有菜单栏的全屏模式3.全屏模式4.只显…

《PostgreSQL事务管理深入解析》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…