vue3+ts+elementui-plus二次封装树形表格实现不同层级展开收起的功能

news2024/11/17 5:52:48

一、TableTreeLevel组件 

<template>
      <div class='main'>
            <div class="btns">
                  <el-button type="primary" @click="expandLevel(1)">展开一级</el-button>
                  <el-button type="primary" @click="expandLevel(2)">展开二级</el-button>
                  <el-button type="primary" @click="expandLevel(3)">展开三级</el-button>
                  <el-button type="primary" @click="expandLevel(4)">展开四级</el-button>
                  <el-button type="warning" @click="putAwayLevel(0)">全部收起</el-button>
            </div>
            <div>
                  <el-table ref="multipleTableRef" :height="height" :default-expand-all="isExpend" :data="treeTableData"
                        style="width: 100%; margin-bottom: 20px" row-key="id" border>
                        <el-table-column :width="item.width" :fixed="item.fixed" show-overflow-tooltip align="center"
                              v-for="(item, i) in treeTableProps" :key="i" :label="item.label">
                              <template #default="scope">
                                    <!-- 自定义插槽展示 -->
                                    <slot v-if="item.slot" :name="item.prop" :scope="scope"></slot>
                                    <!-- 非自定义处理(判空) -->
                                    <span v-else-if="scope.row[item.prop] === '' || scope.row[item.prop] === null">--</span>
                                    <!-- 非自定义处理(正常展示) -->
                                    <span v-else>{{ scope.row[item.prop] }}</span>
                              </template>
                        </el-table-column>
                  </el-table>
            </div>
      </div>
</template>

<script lang="ts" setup>
import { ref, reactive, getCurrentInstance, onMounted, watch } from 'vue'
interface Props {
      // 属性名
      prop: string,
      // 属性标签
      label: string,
      // 是否固定(非必填)
      fixed?: boolean,
      // 行宽(非必填)
      width?: number,
      // 是否显示插槽(非必填)
      slot?: boolean,
}
const props = defineProps({
      /** 表格数据 */
      treeTableData: {
            type: Array,
            default: null,
            required: true
      },
      /** 表格属性 */
      treeTableProps: {
            type: Array<Props>,
            default: null,
            required: true
      },
      /** 是否默认全部展开 */
      isExpend: {
            type: Boolean,
            default: false,
            required: false
      },
      /** 表格高度 */
      height: {
            type: String,
            default: '60vh',
            required: false
      }
})
const multipleTableRef = ref() //获取table的ref
const expandNum = ref(0) //展开层级的数字

/** 监听展开的层级数,如果当前选择的层级小于上一次选择的层级,就收起 */
watch(expandNum, (newValue, oldValue) => {
      if (newValue < oldValue) {
            putAwayLevel(newValue + 1)
      }
}, { deep: true })
/** 收起 */
const putAwayLevel = (num: number) => {
      let arr = ref(treeToArray(props.treeTableData))//将树形数据转为一维数组,方便一层遍历
      // 遍历收起当前层级
      arr.value.map((row: any) => {
            if (num == row.level) {
                  multipleTableRef.value.toggleRowExpansion(row, false);
            }
      })
      // 下面递归调用目的是:假如你展开了4级,又点击展开2级,这时需要收起的是3级和4级,
      // 不然它只收起的2级,点开2级的时候,3级其实也是展开的.
      // 因此细节一点就是:展开2级,需要收起3、4级;展开1级,需要收起2、3、4级;展开3级,需要收起4级;
      if (++num < 4) {
            putAwayLevel(num)
      }
}
/** 展开 */
const expandLevel = (num: number) => {
      expandNum.value = num
      setExpandKeys(props.treeTableData, num)
}

/** 递归设置展开层级 */
const setExpandKeys = (dataList: any, level: number) => {
      // level为要展开的层级,先减一后使用,不然会多展开一级
      --level;
      // 当num大于0时,就对数组里面每一层依次进行展开
      if (level >= 0) {
            for (var i = 0; i < dataList.length; i++) {
                  // toggleRowExpansion 用于可扩展的表格或树表格, 第二个参数为true则为展开该行,false为折叠。
                  multipleTableRef.value.toggleRowExpansion(dataList[i], true);
                  if (dataList[i].children) {
                        setExpandKeys(dataList[i].children, level);
                  }
            }
      }
}
/** 将树形数据转为一维数组的函数*/
const treeToArray = (arr: any) => {
      let data = JSON.parse(JSON.stringify(arr))
      let newData = ref([] as any)
      const callback = (item: any) => {
            (item.children || (item.children = [])).map((v: any) => {
                  callback(v)
            })
            delete item.children
            newData.value.push(item)
      }
      data.map((v: any) => callback(v))
      return newData
}
onMounted(() => {
})

</script>
<style scoped lang='less'>
.btns {
      margin-bottom: 20px;
}

@media screen and (min-width: 200px) and (max-width: 1600px) {}

@media screen and (min-width: 1601px) {}
</style>

二、使用

<!----------------------------BaseTableTreeLevel的使用------------------------------->
		<BaseTableTreeLevel :treeTableData="tableData" height="50vh" :treeTableProps="treeTableProps">
		</BaseTableTreeLevel>
<script lang='ts' setup>
import TableTree from '@/components/BaseTableTree/index.vue'
import { ref, reactive, getCurrentInstance, onMounted } from 'vue'
// 定义表格数据接口
interface dataList {
	id: number
	date: string
	name: string
	address: string
	hasChildren?: boolean
	level: number,
	children?: dataList[]
}
// 定义表格头部属性名
const treeTableProps = [
	{ prop: 'date', label: '日期', width: 300, fixed: true, },
	{ prop: 'name', label: '名称', },
	{ prop: 'address', label: '地址', slot: true, },
]
// 定义表格假数据
const tableData: dataList[] = [
	{
		id: 1,
		date: '2016-05-04',
		name: '',
		address: 'No. 189, Grove St, Los Angeles',
		level: 1,
		children: [
			{
				id: 11,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
				children: [
					{
						id: 111,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
					},
					{
						id: 112,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
					}
				]
			},
			{
				id: 12,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
			},
		],
	},
	{
		id: 2,
		date: '2016-05-04',
		name: '小明',
		address: 'No. 189, Grove St, Los Angeles',
		level: 1,
		children: [
			{
				id: 21,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
				children: [
					{
						id: 211,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
					},
					{
						id: 212,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
					}
				]
			},
			{
				id: 32,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
			},
		],
	},
	{
		id: 3,
		date: '2016-05-01',
		name: '小明',
		level: 1,
		address: 'No. 189, Grove St, Los Angeles',
		children: [
			{
				id: 31,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
				children: [
					{
						id: 311,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
					},
					{
						id: 312,
						date: '2016-05-01',
						name: '小明',
						address: 'No. 189, Grove St, Los Angeles',
						level: 3,
						children: [
							{
								id: 3121,
								date: '2016-05-01',
								name: '小明',
								address: 'No. 189, Grove St, Los Angeles',
								level: 4,
							}, {
								id: 3122,
								date: '2016-05-01',
								name: '小明',
								address: 'No. 189, Grove St, Los Angeles',
								level: 4,
							},
						]
					}
				]
			},
			{
				id: 32,
				date: '2016-05-01',
				name: '小明',
				address: 'No. 189, Grove St, Los Angeles',
				level: 2,
			},
		],
	},
	{
		id: 4,
		date: '2016-05-03',
		name: '小明',
		address: 'No. 189, Grove St, Los Angeles',
		level: 1,
	},
]

onMounted(() => {
})
 
</script>

三、效果

我只定义了三层数据,就只演示展开了三层,还可以多层,自己设置即可 

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

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

相关文章

管理类联考——写作——素材篇——论说文——企业管理故事

文章目录 经典管理案例——武装经管知识&#xff0c;让考官刮目相看分槽喂马金蝉脱壳欲取先与窃符救赵尺蠖huo求伸声东击西借尸还魂以静制动釜底抽薪围师必阙撒豆成兵不入虎穴焉得虎子八坛七盖 经典管理案例 ——武装经管知识&#xff0c;让考官刮目相看 纵使是世界顶级的管理…

音视频入门之音频采集、编码、播放

作者&#xff1a;花海blog 今天我们学习音频的采集、编码、生成文件、转码等操作&#xff0c;我们生成三种格式的文件格式&#xff0c;pcm、wav、aac 三种格式&#xff0c;并且我们用 AudioStack 来播放音频&#xff0c;最后我们播放这个音频。 使用 AudioRecord 实现录音生成…

【Chat GPT】用 ChatGPT 运行 Python

前言 ChatGPT 是一个基于 GPT-2 模型的人工智能聊天机器人&#xff0c;它可以进行智能对话&#xff0c;同时还支持 Python 编程语言的运行&#xff0c;可以通过 API 接口进行调用。本文将介绍如何使用 ChatGPT 运行 Python 代码&#xff0c;并提供一个实际代码案例。 ChatGPT …

苹果mac电脑好用的pdf编辑工具PDF Expert 最新中文 v3.2.2

PDF Expert提供了丰富的PDF编辑功能&#xff0c;包括添加、删除、移动、旋转、缩放、裁剪等操作&#xff0c;以及文本、图像、链接、表格、注释等元素的添加和修改。 行云如水&#xff01;阅读PDF文档非常流畅&#xff0c;不管你的文件有多大。编辑PDF文档 以简单快速度编辑PD…

兴达易控 ETHERCAT转PROFIBUS从站网关配置方式

ETHERCAT转PROFIBUS&#xff08;XD-ECPBS20&#xff09;是一款PROFIBUS从站功能的通讯网关。ETHERCAT转PROFIBUS从站网关主要功能是将ETHERCAT设备接入到PROFIBUS网络中。 本网关连接到PROFIBUS总线中做为从站使用&#xff0c;连接到ETHERCAT总线中做为从站使用。 1、配置网关…

基于RWEQ模型的土壤风蚀模数估算及其变化归因分析教程

详情点击公众号链接&#xff1a;基于RWEQ模型的土壤风蚀模数估算及其变化归因分析 前沿 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160…

学习笔记20 Java Collections Framework概览

一、Lists, Sets, and Maps list按位置对元素排序&#xff0c;元素x在列表中的位置&#xff0c;也称为其索引。一个列表允许重复的元素。list通过其索引来区分相同的对象。 set是无序无重复集合。与列表不同&#xff0c;set没有其元素的位置概念。集合的实现通常针对搜索进行…

C++-----stack和queue

本期我们来学习stack和queue 目录 stack介绍 栈的使用 栈的模拟实现 queue介绍 队列的使用 队列的模拟实现 deque 优先级队列 模拟实现 仿函数 全部代码 stack介绍 1. stack 是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除…

亚马逊测评自养号:如何正确选择学习对象与获取可靠技术知识?

亚马逊是一家知名的跨境电商平台&#xff0c;吸引了越来越多的人涉足这个领域。随着商家数量的增加&#xff0c;亚马逊的竞争力也在不断提高。在亚马逊平台上&#xff0c;产品评价对于卖家账号的评估以及产品曝光量、销量等方面具有直接影响。因此&#xff0c;对于任何一个希望…

单路 PWM 控制的高调光比 LED 降压恒流控制器

概述 OC5401 是一款单路 PWM 控制的高调光比降压恒流驱动控制器&#xff0c;PWM 调光比最高可达 10000&#xff1a;1。 OC5401 支持 16-60V 输入电压范围。 OC5401 采用电流滞环控制方式&#xff0c;无需环路补偿。 OC5401 可通过外接电阻设置 LED 输出电流&#xff0c;最…

数据库中的事务处理

MySQL的事务处理&#xff1a;只支持 lnnoDB 和BDB数据表类型 1.事务就是将一组SQL语句放在同一批次内去执行 2.如果一个SQL语句出错&#xff0c;则该批次内的所有SQL都将被取消执行 MySQL的事务实现方法一&#xff1a; select autocommit 查询当前事务提交模式 set a…

【第二套】Java面试题

第二套&#xff1a; 一、JavaScript前端开发 1、下列的代码输出什么&#xff1f; var y 1; if(function f(){}){y typeof f; } console.log(y);正确的答案应该是 1undefined。 JavaScript中if语句求值其实使用eval函数&#xff0c;eval(function f(){}) 返回 function f()…

Web前端 常用布局

Flex布局&#xff08;弹性布局&#xff09; 参考&#xff1a;滑动验证页面 space-between与space-around的区别

Python编程很简单,四步菜鸟到高手(文末送书5本)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

别在找git报错的解决方案啦,多达20条git错误解决方案助你学习工作

1. 找不到Git命令 $ sudo apt-get update $ sudo apt-get install git2. 无法克隆远程仓库 $ git clone https://github.com/username/repo.git3. 无法拉取或推送到远程仓库 $ git pull origin master $ git add . $ git commit -m "Resolve conflicts" $ git pus…

java.lang.ClassNotFoundException: sun.misc.BASE64Decoder

有一个新的应用服务&#xff0c;idea启动应用应用服务时&#xff0c;突然报错java.lang.ClassNotFoundException: sun.misc.BASE64Decoder &#xff0c;然后在网上搜索&#xff0c;说是建议使用apache包&#xff0c;该类新的JRE已经废弃&#xff0c;并从rt.jar包中移除。但是该…

Visual Components数字化工厂仿真软件 衡祖仿真

Visual Components 3D 制造仿真软件可以方便快捷地设计和验证新的生产解决方案&#xff0c;可以向用户提供快速、便捷、真实的智能制造仿真解决方案。 一、数字化工厂产线仿真 VisualComponents仿真软件将离散物流事件仿真、人机协作、机器人工艺仿真和虚拟调试集于一个平台&am…

【Matter】基于Ubuntu 22.04 编译chip-tool工具

前言 编译过程有点曲折&#xff0c;做下记录&#xff0c;过程中&#xff0c;有参考别人写的博客&#xff0c;也看github 官方介绍&#xff0c;终于跑通了~ 环境说明&#xff1a; 首先需要稳定的梯子&#xff0c;可以访问“外网”ubuntu 环境&#xff0c;最终成功实验在Ubunt…

#P1005. [NOIP2010普及组] 导弹拦截

题目描述 经过 1111年的韬光养晦&#xff0c;某国研发出了一种新的导弹拦截系统&#xff0c;凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为 00时&#xff0c;则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷&#xff1a;每套系…

L2Cache 核心原理解析

源码地址&#xff1a;L2Cache L2Cache是什么 L2Cache 是一个基于内存、 Redis 、 Spring Cache 实现的满足高并发场景下的分布式二级缓存框架。 L2Cache如何使用 如何使用 L2cache L2Cache架构图 核心逻辑 1、发起 get(key) 请求2、从localCache中get缓存&#xff0c;若存…