Vue2 + Element UI 封装 Table 递归多层级列表头动态

1、在 components 中创建 HeaderTable 文件夹,在创建 ColumnItem.vue 和 index.vue。

如下:

2、index.vue 代码内容,如下:

<template><div><el-table:data="dataTableData"style="width: 100%"max-height="700":cell-style="{'border-right': '1px solid #C4C6CB','border-bottom': '1px solid #C4C6CB',}":header-cell-style="{'background-color': '#f8f8f9','border-right': '1px solid #C4C6CB','border-bottom': '1px solid #C4C6CB',}"><el-table-columnprop="date"label="时间"width="150"align="center"v-if="flag"></el-table-column><!-- 递归组件 --><template v-if="flag"><ColumnItemv-for="(item,index) in dataHeaders":key="item.label":col="item":maxLength="maxLength"></ColumnItem></template><el-table-columnprop=""width="150"align="center"v-if="showAddBut && flag"><template slot="header" slot-scope="scope"><i class="el-icon-plus" @click="getAdd({})"/></template></el-table-column></el-table><el-drawer:title="title":visible.sync="drawer":size="350"direction="ltr":before-close="handleClose"><el-form:inline="true":model="column"label-position="right"label-width="auto"ref="ruleFormRef":rules="rules"class="demo-form-inline form-padding"><el-form-item label="名称" prop="label"><el-input v-model="column.label" placeholder="请输入名称" clearable /></el-form-item><el-form-item label="宽度" prop="width"><el-inputv-model="column.width"type="number"placeholder="请输入列宽度(不填为自适应)"clearable/></el-form-item><el-form-item label="对齐方式" prop="align"><el-selectv-model="column.align"placeholder="请选择对齐方式"clearable><el-option label="左对齐" value="left" /><el-option label="居中对齐" value="center" /><el-option label="右对齐" value="right" /></el-select></el-form-item><el-form-item label="映射变量" prop="prop"><el-cascaderv-model="column.prop":options="options":props="optionProps"@change="handleChange"></el-cascader></el-form-item></el-form><div class="drawer-footer"><el-button @click="handleClose">取消</el-button><el-button type="primary" :loading="loading" @click="handleSubmit">{{ submitText }}</el-button></div></el-drawer></div>
</template><script>
import { EventBus } from "../../utils/event-bus.js";
import ColumnItem from './ColumnItem.vue';
import { apiEditHeaderTable, apiGetList, apiGetTreeselect } from "@/api/headerTable/index.js";
export default {name: 'CustomElTable',components: {ColumnItem},props: {// 表头数据headers: {type: Array,required: true},// 表格列表数据tableData: {type: Array,required: true},// 区分哪个页面下的列表tablekey: {type: String,required: true},// 限制新增最大列maxLength: {type: Number,required: false},},data() {return {dataHeaders: this.headers,dataTableData: this.tableData,dataNum: this.num,flag: true, // 为了更新子组件的状态drawer: false,loading: false,column: {label: "",width: "",align: "center",prop: "",},optionProps: { expandTrigger: 'click',value: "id",label: "label",children: "children",},copyCol: {},rules: {label: [{ required: true, message: "请输入名称", trigger: "blur" }],align: [{ required: true, message: "请选择对齐方式", trigger: "blur" }],},title: '新增列',submitText: '新增',options: [],}},computed: {showAddBut() {return this.$store.state.common.headerEditBut}},watch: {headers: {handler(newValue,oldValue) {this.dataHeaders = newValue;}},},methods: {// 删除getDelete(col) {this.$confirm('是否删除?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(_ => {let newHeaders = this.getRecursion(this.dataHeaders,col);console.log("处理完数据的", newHeaders);this.dataHeaders = newHeaders;// 数据更新,更新子组件状态this.flag = false;this.$nextTick(() => {this.flag = true;})EventBus.$emit("getHeaders",this.headers)}).catch(() => {});},// 递归删除getRecursion(arr,col) {arr.map((item,index) => {if(item.label === col.label && item.deep === col.deep) {arr.splice(index,1);return;}if(item.children && item.children.length > 0) {this.getRecursion(item.children,col)}})return arr;},// 新增getAdd(col) {this.drawer = true;this.title = '新增列';this.submitText = '新增';this.column.label = '新增列';this.copyCol = col;},// 编辑getEdit(col) {this.drawer = true;this.title = '编辑列',this.submitText = '保存',this.column.label = col.label;this.copyCol = col;},// 编辑,新增里的取消handleClose() {this.$confirm('内容未保存,确认关闭?','提示',{confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(_ => {this.drawer = false;}).catch(_ => {});},// 编辑,新增里的保存handleSubmit() {let col = this.copyColthis.loading = true;let item = {label: this.column.label,prop: "",width: this.column.width,align: this.column.align,deep: 1,selected: false,children: []}if(this.title === '新增列') {if(!Object.keys(col).length == 0){item.deep = col.deep + 1;col.children.push(item);}else {this.dataHeaders.push(item);}}else {this.flag = false;this.$nextTick(() => {this.flag = true;col.label = this.column.label;col.width = this.column.width;col.align = this.column.align;col.prop = this.column.prop;})}this.loading = false;this.drawer = false;console.log("dataHeaders", this.dataHeaders);// this.handleApi();},// 请求接口,保存表头数据handleApi() {let data = {tableKey: this.tablekey,tableJson: JSON.stringify(this.dataHeaders)}apiEditHeaderTable(data).then(() => {this.loading = false;this.drawer = false;this.$message({message: '编辑成功',type: 'success'});}).catch(() => {this.loading = false;this.drawer = false;this.$message({message: '编辑失败',type: 'error'});})},handlePreserve() {console.log("保存");this.handleApi();},//handleChange(val) {let aa = val[val.length-1]apiGetList({deptId: aa}).then(res => {console.log(">>>>",res);})},handleList() {let data = {}apiGetTreeselect(data).then((res) => {this.options = res.data;})}},mounted() {this.handleList();console.log("tablekey",this.tablekey);EventBus.$on("getDelete",(col) => {this.getDelete(col)});EventBus.$on("getAdd",(col) => {this.getAdd(col)});EventBus.$on("getEdit",(col) => {this.getEdit(col)});EventBus.$on("handlePreserve",() => {this.handlePreserve()});}
}
</script><style lang="scss" scoped>
.scope_p {margin: 0;
}
.i_margin {margin: 0 10px;
}.content-main {.table-title {display: flex;justify-content: space-around;margin-bottom: 10px;> p {flex: 1;font-weight: bold;font-size: 18px;}}.el-input {width: 250px;}.el-select {width: 280px;}
}
.form-padding {padding: 0 20px;
}
.drawer-footer {display: flex;align-items: center;justify-content: center;
}.header-btn {display: flex;align-items: center;justify-content: center;.el-icon-plus {margin-left: 10px;cursor: pointer;}.el-icon-edit {margin-left: 10px;cursor: pointer;}.el-icon-delete {margin-left: 10px;cursor: pointer;}
}.selected {color: #409eff;
}.header-scroll::v-deep {.el-table__header-wrapper {overflow-x: auto;}/* 修改滚动条样式 */::-webkit-scrollbar {height: 8px; /* 设置滚动条宽度 */}::-webkit-scrollbar-track {background-color: #ffffff; /* 设置滚动条轨道背景色 */}::-webkit-scrollbar-thumb {background-color: #ececec; /* 设置滚动条滑块颜色 */border-radius: 4px; /* 设置滚动条滑块圆角 */}::-webkit-scrollbar-thumb:hover {background-color: #e2e2e2; /* 设置滚动条滑块鼠标悬停时颜色 */}
}
.error_label {color: #f56c6c !important;
}
</style>

3、ColumnItem.vue 代码内容,如下:

<template><el-table-column:prop="col.prop":width="col.width":align="col.align"min-width="150"><template slot="header" slot-scope="scope"><p class="scope_p">{{col.label}}</p><div v-if="showAddBut"><i class="el-icon-plus" v-if="col.deep < maxLength" @click="Add(col)"/><i class="el-icon-edit-outline i_margin" @click="Edit(col)"/><i class="el-icon-delete" @click="Delete(col)"/></div></template><!-- 遍历递归 --><template v-for="(item,index) in col.children"><ColumnItem v-if="item.children" :col="item" :key="item.label" :maxLength="maxLength"/></template></el-table-column>
</template><script>
import { EventBus } from "../../utils/event-bus.js";
export default {name: "ColumnItem",props: {col: {type: Object,required: true},maxLength: {type: Number,required: false},},methods: {Add(col) {EventBus.$emit("getAdd",col)},Edit(col) {EventBus.$emit("getEdit",col)},Delete(col) {console.log(col);EventBus.$emit("getDelete",col)}},computed: {showAddBut() {return this.$store.state.common.headerEditBut}},mounted() {},
}
</script><style lang="scss" scoped>
.scope_p {margin: 0;
}
i {cursor: pointer;
}
.i_margin {margin: 0 10px;
}
</style>

4、在 .vue 文件中使用和数据,如下: 

<HeaderTable :headers="headers" :tableData="tableData" :tablekey="tablekey" :maxLength="4"/>
data() {return {headers: [{label: "1",prop: "name",width: "150",align: "center",deep: 1,selected: false,children: [{label: "1-1",prop: "",width: "",align: "center",deep: 2,selected: false,children: [{label: "1-1-1",prop: "",width: "",align: "center",deep: 3,selected: false,children: []}]},{label: "1-2",prop: "",width: "",align: "center",deep: 2,selected: false,children: []}]},{label: "2",prop: "name",width: "150",align: "center",deep: 1,selected: false,children: [{label: "2-1",prop: "",width: "",align: "center",deep: 2,selected: false,children: [{label: "2-1-1",prop: "",width: "",align: "center",deep: 3,selected: false,children: []},{label: "2-1-2",prop: "",width: "",align: "center",deep: 3,selected: false,children: []}]},{label: "2-2",prop: "",width: "",align: "center",deep: 2,selected: false,children: []}]}],tableData: [{date: '2016-05-03',}, {date: '2016-05-02',}, {date: '2016-05-04',}, {date: '2016-05-01',}, {date: '2016-05-08',}, {date: '2016-05-06',}, {date: '2016-05-07', }],}
}

5、效果图,如下:

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

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

相关文章

OSM历史10年(2014-2024)全国数据下载(路网、建筑物、POI、水系、地表覆盖利用······)

点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 零、前沿 这次向大家介绍一下OSM&#xff08;OpenStreetMap&#xff09;十年历史数据&#xff08;2014—2014&#xff09;的下载方法。当然我们也下载好分享给大家&#xff…

JAVA web期末复习总结

C/S结构与B/S结构区别&#xff1a; 在C/S结构中&#xff0c;客户端通常是一个独立的应用程序&#xff0c;需要在用户的计算机上安装和运行。而在BS结构中&#xff0c;客户端是一个Web浏览器&#xff0c;用户只需要通过浏览器打开网页&#xff0c;不需要安装额外的应用程序。 C…

程序员上岸指南

如果你还在996&#xff0c;大小周&#xff0c;感觉身体被掏空&#xff0c;那么你可以看看下面这篇文章&#xff0c;我特意搜集了一些苦逼程序员的上岸教程。 人生真的就是做几道选择题&#xff0c;选错了&#xff0c;忙也是瞎忙。选对了&#xff0c;躺着都能赢。总的来说&#…

良心推荐:什么软件能够监控公司电脑,就这5款软件能监控公司电脑

用软件监控员工电脑在大多数国家是非法的&#xff0c;不过在中国&#xff0c;企业在办公场所安装监控设备以监控员工工作&#xff0c;在遵循一定限制和条件的前提下&#xff0c;是合法的。以下是一些符合这些条件&#xff0c;并且广泛被企业采用的员工电脑监控软件的良心推荐&a…

C++:儿童节快乐呀!

六一快乐&#xff01;~ 今天我来宣布一个 ——————Cookie Maker工作室成立了&#xff01;—————— 目前参与人数&#xff1a;7 人名列单&#xff1a; 真实姓名 联系方式以及用户名 ZINCFFO CSDN&#xff08;ZINCFFO&#xff09; &…

使用 Scapy 库编写 IP 地址欺骗攻击脚本

一、介绍 1.1 概述 IP地址欺骗&#xff08;IP Spoofing&#xff09;是一种网络攻击技术&#xff0c;攻击者伪造其数据包的源IP地址&#xff0c;使其看起来像是从其他合法地址发送的。这种技术常用于各种攻击中&#xff0c;例如DDoS攻击、Man-in-the-Middle&#xff08;MITM&a…

buidldroot musl uclib库 编译

buildroot 修改 编译工具链 原本编译器相关信息&#xff1a; Incorrect selection of the C library buidroot编译 注意相关选项&#xff0c;后续使用CUSTOM TOOLCHAIN 时对应 UCLIB 能将生成IMAGE 从2.9K变为2.3K MUSL 能将生成IMAGE 从2.9K变为2.7K 变大了 arm-linux-…

c++的string一键介绍

前言&#xff1a; 这篇文章旨在帮助读者回忆如何使用string&#xff0c;并提醒注意事项。它不是一篇详细的功能介绍&#xff0c;而是一篇润色文章。 先展示重载函数&#xff0c;如果该函数一笔不可带过&#xff0c;就先展示英文原档&#xff08;附带翻译&#xff09;&#xf…

教你搞一个比较简单的计时和进度条装饰器

教你搞一个比较简单的计时和进度条装饰器 什么是装饰器为啥要用装饰器呢&#xff1f;上代码&#xff01;如何使用装饰器效果 什么是装饰器 装饰器的英文是&#xff1a;Decorator。装修的英文是&#xff1a;Decoration。顾名思义就是我们要用装饰器在函数func()上搞点儿事儿&am…

原生APP开发和Flutter开发的比较

原生APP开发和Flutter开发各有优缺点&#xff0c;适用于不同的场景和需求。下面是两者的详细比较&#xff0c;从开发语言、性能、开发效率、维护和更新、社区和支持等多个方面进行分析。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。…

htb_BoardLight

信息收集 nmap -sSVC 10.10.11.11开放80端口&#xff0c;将boardlight.htb写入/etc/hosts 同步进行子域名和目录扫描 子域名扫不到 这个目录扫描很奇怪哈&#xff0c;明明访问80端口有页面&#xff0c;就是扫不出来 直接浏览器访问80端口&#xff0c;四处看看&#xff0c;发…

7、架构-架构的安全性

即使只限定在“软件架构设计”这个语境下&#xff0c;系统安全仍然是一 个很大的话题。我们谈论的计算机系统安全&#xff0c;不仅仅是指“防御系统 被黑客攻击”这样狭隘的安全&#xff0c;还至少应包括&#xff08;不限于&#xff09;以下这些问 题的具体解决方案。 认证&am…

自定义数据集训练 Yolo V10

上次介绍了Yolo 推理&#xff0c;本文我们将使用自己的数据集训练 Yolo V10&#xff0c;训练过程简单&#xff1a; 首先准备数据集&#xff0c;包括图片、标注训练推理 数据集准备 本次采用的数据集为内部数据&#xff0c;标注方法为 VOC 格式&#xff0c;首先我们需要建 VO…

智能辅导班技术架构:运用人工智能提升教育领域的学习效果

在教育领域&#xff0c;随着人工智能的发展&#xff0c;智能辅导班逐渐成为一种趋势。它利用先进的技术和创新的教学方法&#xff0c;为学生提供个性化的学习体验和全方位的辅导服务。本文将介绍智能辅导班的技术架构&#xff0c;探讨如何运用人工智能来提升学习效果。 ### 1. …

力扣之链表专题

1. (LeetCode-21)合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 …

微服务架构-微服务实施

目录 一、概述 二、微服务拆分 2.1 概述 2.2 拆分原则 2.3 拆分方法 2.3.1 以数据为维度进行拆分 2.3.2 按照使用场景拆分 2.3.3 重要和非重要的拆分 2.3.4 变和不变的拆分 三、微服务通信 3.1 概述 3.2 微服务通信方式选择 3.3 微服务编排 3.4 API接口设计 3.5 …

「计网」网络初识

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;计网 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 网络初识 &#x1f349;IP 地址 & 端口号&#x1f349;网络协议&#x1f34c;TCP/IP 网络协议 &#x1f349;封装和分用&#x1f349…

乡村振兴与乡村旅游创新:创新乡村旅游产品,提升旅游服务水平,打造特色乡村旅游品牌,助力美丽乡村建设

目录 一、引言 二、乡村旅游产品的创新 &#xff08;一&#xff09;挖掘乡村特色资源 &#xff08;二&#xff09;注重产品体验性 &#xff08;三&#xff09;创新旅游产品形态 三、旅游服务水平的提升 &#xff08;一&#xff09;加强基础设施建设 &#xff08;二&…

如何上传模型素材创建3D漫游作品?

一、进入3D空间漫游互动工具编辑器 进入720云官网-点击“开始创作”-选择3D空间漫游-进入到作品创建页面。 二、上传模型及素材&#xff0c;创建生成3D空间漫游模型 1.创建3D空间作品&#xff1a;您可以选择新建空白作品或使用720云提供的预设空间模板&#xff0c;本篇主要介绍…

[手游] Florence逝去的爱弗洛伦斯

图片处理工具箱Hummingbird : Hummingbird使用智能压缩技术来减少文件的大小&#xff0c;支持&#xff1a;jpg、png、webp、svg、gif、gif、css、js、html、mp4、mov&#xff0c;可以设置压缩的同时等比例缩放图片或视频的尺寸。可以拖放文件夹压缩&#xff0c;一次最多可处理1…