【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,一经查实,立即删除!

相关文章

金融投资公司如何实现创新, 盛创汇凭借人工智能站上硬科技C位

作为硬科技产业的重要组成部分,近年人工智能受到了国家政策的高度重视。 在《 “十四五”规划和2035年远景目标纲要》中,人工智能被摆放在科技前沿领域攻关方面的首要位置,先后八次被提及。《规划》指出,对新一代人工智能,要在前沿基础理论突破,专用芯片研发,深度学习框架等开…

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块代理…

Python 的运算符和语句(条件、循环、异常)基本使用指南

运算符的分类 算数运算符赋值运算符复合赋值运算符比较运算符逻辑运算符 算数运算符 运算符描述实例加1 1 输出结果为 2-减1 - 1 输出结果为 0*乘2 * 2 输出结果为 4/除10 / 2 输出结果为 5//整除9 // 4 输出结果为 2%取余9 % 4 输出结果为 1**指数2 ** 4 输出结果为 16&…

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

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

Learn Prompt-经验法则

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

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

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

非独立随机变量的概率上界估计

目前的概率论或者随机变量书籍过分强调对独立随机变量的大数定律&#xff0c;中心极限定理&#xff0c;遗憾上界的估计。而对于非独立随机变量的研究很少&#xff0c;在《概率论的极限定理》中曾给出过一般随机变量求和的渐进分布簇的具体形式&#xff0c;然而形式却太过复杂。…

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

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

谁在遥遥领先

结合HC发布的最新消息以及外围爆料&#xff0c;预计华为将在发布会上推出7款新品&#xff0c;包括智能手机、平板电脑、智能电视、智能手表、耳机和其他智能配件。这其中&#xff0c;最受期待的肯定是Mate系列真正的底牌——Mate60 RS&#xff0c;亦或更高端的手机产品。 具体…

.NET Upgrade Assistant 升级 .NET MAUI

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

fastadmin 基本使用配置

fastadmin 版本 1.3.5 thinkphp 版本 5.0.25 配置 cache 为 redis 保存 // ---------------------------------------------------------------------- // | 缓存设置 // ---------------------------------------------------------------------- cache …

[交互]AJAX

[交互]AJAX 创建 XMLHttpRequest发送请求服务器响应XMLHttpRequest readyState 状态值响应数据请求状态变更回调函数XMLHttpRequest status 的值常用状态码设置 AJAX 是技术&#xff0c;不是工具&#xff0c;区别于 axios、fetch、$.ajax 等(封装工具)现有交互工具,是用于改变部…

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

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

Mysql的定时备份与恢复

MySQL定时备份与还原 MySQL备份方案 物理备份 这种备份方式将数据库的实际文件复制到另一个位置。常见的物理备份工具包括mysqldump和Percona XtraBackup。具体操作如下&#xff1a; 使用mysqldump 命令备份数据库&#xff1a; mysqldump -u username -p database_name >…

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

| 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"键退出编辑…