当前位置: 首页 > news >正文

基于 elements3 包装的 可展开 table 组件

基于 elements3 包装的 可展开 table 组件

1.手风琴效果,一次只能展开一个

2.动态加载 展开内容 (根据接口)

效果:

<template><el-tableref="tableRef":data="tableData"v-loading="loading"v-if="columns.length > 0"style="width: 100%"@expand-change="handleExpand"class="custom-expend-table"header-row-class-name="custom-table-header"row-class-name="custom-table-row"@row-click="handleClick"><!-- 折叠列 --><el-table-column type="expand" v-if="hasExpand" width="20"><template #default="{ row }"><div class="expand-content-wrapper"><el-tablev-if="childDataMap[row[rowKey]]?.length":data="childDataMap[row[rowKey]]"size="small"header-row-class-name="child-table-header"row-class-name="child-table-row"><el-table-columnv-for="col in childColumns":key="col.column":label="col.showName":prop="col.column":min-width="col.width || col.column === 'month' ? 50 : 80"align="center"><template #default="{ row }">{{ row[col.column] || '-' }}</template></el-table-column></el-table><div v-else class="text-gray-500 text-center py-4 empty-box">{{ expandLoadingMap[row[rowKey]] ? '加载中...' : '暂无数据' }}</div></div></template></el-table-column><!-- 主表列 --><el-table-columnv-for="col in columns":key="col.column":prop="col.column":label="col.showName":min-width="col.width || col.column === 'year' ? 50 : 80"align="center"><template #default="{ row }">{{ row[col.column] || '-' }}</template></el-table-column><template #empty><EmptyBox desc="无数据" v-if="height" :height="'auto'" /><EmptyBox desc="无数据" v-else /></template></el-table>
</template><script setup lang="ts">
import { ref , PropType,computed } from 'vue'
import { ElMessage } from 'element-plus'
import {sortByDate} from "@/utils/formate/sort_formate";
import { isEqual  } from 'lodash-es';const props = defineProps({height: {type: [String, Boolean],default: '180'},tableData: {type: Array as PropType<any[]>,required: true,},columns: {type: Array as PropType<any[]>, // 使用定义好的 Column 类型required: true,}, // 主表字段rowKey: {type: String,default: 'id',},fetchChildData: {type: Function || Function as PropType<(row: any) => Promise<any>> ,required: false,default: undefined},loading: {type: Boolean,default: false,},isThrottle: {type: Boolean,default: false,}
})const hasExpand = computed(() => typeof props.fetchChildData === 'function')// 保存每行子表数据
const childDataMap = ref<Record<string, any[]>>({})
const childColumns = ref<any[]>([])
const expandLoadingMap = ref<Record<string, boolean>>({})// 展开行触发:异步加载子表
const handleExpand = async (row: any, expanded: any[]) => {const rowKey: any = row[props.rowKey]// 当前展开的 rowKey(row 点击后立即触发)const isExpanding: any = expanded.some((t: any) => rowKey == t[props.rowKey])// 收起时清空记录if (!isExpanding) {if (currentExpandedRowKey.value === rowKey) {currentExpandedRowKey.value = null}return}// 若当前点击的不是同一行,先收起上一个if (currentExpandedRowKey.value && currentExpandedRowKey.value !== rowKey) {const prevRow = props.tableData?.find((item: any) => item[props.rowKey] === currentExpandedRowKey.value)if (prevRow && tableRef.value) {tableRef.value.toggleRowExpansion(prevRow, false)}}// 设置当前展开行为当前行currentExpandedRowKey.value = rowKey// 判断是否需要加载数据if (props.isThrottle && childDataMap.value[rowKey]) returnexpandLoadingMap.value[rowKey] = truetry {if (!props.fetchChildData) returnconst { head, data } = await props.fetchChildData(row)sortByDate(data, 'month', 'desc')childDataMap.value[rowKey] = data || []childColumns.value = head || []} catch (err) {ElMessage.error('子表加载失败')childDataMap.value[rowKey] = []} finally {expandLoadingMap.value[rowKey] = false}
}const tableRef = ref()
const currentExpandedRowKey = ref<string | null>(null)
const currentExpandedRow = ref<any>(null)
const handleClick = (row: any) => {if (!hasExpand.value) returnconst rowKey = row[props.rowKey]// 从 tableData 中找到真正要展开的那一行(必要)const matchedRow: any = props.tableData?.find((item: any) => item[props.rowKey] === rowKey)if (!matchedRow) {console.warn('找不到匹配的行数据:', rowKey)return}// 👉 判断是否是“当前已展开的那一行”const isSameRow = (currentExpandedRowKey.value === rowKey &&isEqual(currentExpandedRow.value, matchedRow))// 如果点击的是当前已展开行 → 收起if ( isSameRow ) {tableRef.value.toggleRowExpansion(matchedRow, false)currentExpandedRowKey.value = nullcurrentExpandedRow.value = nullreturn}// 收起之前已展开的if (currentExpandedRowKey.value !== null) {const prevRow = props.tableData.find((item: any) => item[props.rowKey] === currentExpandedRowKey.value)if (prevRow) {tableRef.value.toggleRowExpansion(prevRow, false)}}// 展开新行tableRef.value.toggleRowExpansion(matchedRow, true)currentExpandedRowKey.value = rowKeycurrentExpandedRow.value = matchedRow
}defineExpose({handleClick,
});</script>

使用:

    <CustomExpandTableref="expandTable":columns="tableData.head":tableData="tableData.data":fetchChildData="getSubTable"rowKey="stattime"></CustomExpandTable>

http://www.lryc.cn/news/590200.html

相关文章:

  • uniapp各端通过webview实现互相通信
  • 并发编程-CountDownLatch
  • UniApp 多端人脸认证图片上传实现
  • 【PTA数据结构 | C语言版】前缀树的3个操作
  • 关于程序=数据结构+算法这句话最近的一些思考
  • 数字ic后端设计从入门到精通11(含fusion compiler, tcl教学)全定制设计入门
  • Java-数构链表
  • golang语法-----指针
  • 笔试——Day10
  • 简单易懂,什么是连续分配管理方式
  • Qt 将触摸事件转换为鼠标事件(Qt4和Qt5及以上版本)
  • Java线程创建与运行全解析
  • DuckDB 高效导入 IPv6 地址数据的实践与性能对比
  • #Datawhale组队学习#7月-强化学习Task1
  • java解析word文档
  • 使用JS编写一个购物车界面
  • C++ 面向对象
  • 第2章通用的高并发架构设计——2.3 高并发读场景方案2:本地缓存
  • 开源 python 应用 开发(七)数据可视化
  • Linux 定时器应用示例(修正版)
  • GIT版本回退
  • Python中可以反转的数据类型
  • GaussDB 数据库架构师修炼(五) 存储容量评估
  • 搜索框的显示与隐藏(展开与收起)
  • el-input 回显怎么用符号¥和变量拼接展示?
  • openEuler 22.03 LTS Rootless Docker 安装指南
  • MongoDB复杂查询 聚合框架
  • 洛谷 P11247 [GESP202409 六级] 算法学习-普及/提高-
  • pymongo库:简易方式存取数据
  • ETL还是ELT,大数据处理怎么选更靠谱?