ElementUI-tree拖拽功能与节点自定义

前言

在管理端会遇到多分类时,要求有层次展示出来,并且每个分类有额外的操作。例如:添加分类、编辑分类、删除、拖到分类等。

下面将会记录这样的一个需求实习过程。

了解需求

  1. 分类展示按层级展示
  2. 分类根据特定的参数展示可以操作的按钮,分类的操作有增、删、改
  3. 分类还支持拖拽功能,并不是所有的分类都支持拖拽
  4. 点分类去执行别的操作。例如:刷新数据(不实现)
  5. 增加分类之后刷新分类数据,当前选择的分类为增加的分类
  6. 删除分类后回到上一级分类
  7. 右击分类和点击操作按钮均可以弹出操作弹窗
  8. 点击分类前的箭头可展开和折叠分类

效果图

  • 分类展示

  • 分类操作的弹窗

组件库

采用ElementUI 中的 Tree树形控件、Dropdown下拉菜单

  • Tree树形控件:Element - The world's most popular Vue UI framework
  • Dropdown下拉菜单dropdown:Element - The world's most popular Vue UI framework

开始编码

搭建tree 组件

  •   html 部分:
<el-tree :data="classifyData" node-key="id" draggable ref="tree" :accordion="false" auto-expand-parent :default-expanded-keys="[checkedId]" :props="defaultProps":allow-drop="allowDrop" :allow-drag="allowDrag"@node-drag-start="handleDragStart" @node-drop="handleDrop"@node-click="nodeClick" @node-contextmenu="rightClick":show-checkbox="false" :check-strictly="true"  ><div class="custom-tree-node" slot-scope="{ node, data }"><span>{{ data.name }}</span> <span><el-dropdown type="primary" trigger="click" :ref="'messageDrop'+data.id" @visible-change="controlCheckedKeys"><span class="el-dropdown-link" @click.stop="setSeletKey(data.id)">  <img src="~@/../more-active.png" v-if="checkedKeys == data.id"  class="myicon-opt" /> <img src="~@/../more.png" v-else class="myicon-opt" /></span><el-dropdown-menu slot="dropdown"><el-dropdown-item v-if="data.is_add_classify"><div @click="openClassify(data.id,'新增子分类')"><img src="~@/../add.png" class="myicon-opt"/> 新增子分类</div></el-dropdown-item><el-dropdown-item v-if="data.is_edit_sort"><div @click="editClassify(data)"> <img src="~@/../edit.png" class="myicon-opt" /> 修改</div></el-dropdown-item><el-dropdown-item v-if="data.is_edit_sort"><div @click="delBefore(data.id,data.parent_id)"><img src="~@/../del.png" class="myicon-opt" />删除</div></el-dropdown-item></el-dropdown-menu></el-dropdown></span></div></el-tree>
  • css
<style lang="stylus" scoped>
.active{background: #F2F6F9;color: #409EFF;
}
.classify{padding : 0 16px;height: 40px;font-family: PingFangSC-Medium;font-weight: 500;font-size: 15px; line-height:40px;
}.el-tree ::v-deep {.el-tree-node__content{ @extend .classify;&:hover{@extend .active; }.el-tree-node__expand-icon.is-leaf{// display:nonemargin-left:-12px}}.is-checked > .el-tree-node__content{@extend .active;} 
} 
.custom-tree-node{display: flex;justify-content: space-between;width: 100%;
}
.myicon-opt{vertical-align: middle;width: 16px;height: 16px;
} 
</style>
  • js
<script>export default {props:{activeId:{type:[String,Number],default:''},classifyData:{type:Array,default:[]}},watch:{activeId: {handler(v,o){// v 值为0时, 0 == '' 值为trueif (typeof v == 'number') {this.checkedId = v this.$nextTick(()=>{this.$refs.tree.setCheckedKeys([v])}) }},immediate:true,deep:true },},data() {return {checkedId:'', checkedKeys:'', defaultProps: {children: 'child',label: 'name'},classifyCofig:{flag:false,Id: '',title:'',value:''}, }},methods: { // 点击分类名称nodeClick(data,node){ this.checkedId = data.id  this.$refs.tree.setCheckedKeys([data.id]) node.expanded = truethis.$emit('selectId',data.id)// console.log('node',data.id,node.parent)let addId  = [ data.id]if(node.parent.parent != null)  this.selectNode(addId,node.parent)// console.log('addId',addId)this.$emit('selectaddId', addId)},// 获取多层级的父类id加入到数组下标为0的位置selectNode(id,node){ id.unshift(node.data.id)if(node.parent.parent != null){this.selectNode(id,node.parent)} },// 右击分类rightClick(event,data, Node, element){ setTimeout(()=>{this.checkedKeys = data.id this.$refs['messageDrop'+data.id].show() })},// 点击操作按钮setSeletKey(k){ setTimeout(()=>{this.checkedKeys = k})},// 下拉菜单的异步监听,打开(true)还是隐藏(flase)controlCheckedKeys(flag){  if(!flag){this.checkedKeys = ''}},// 节点开始拖拽时触发的事件handleDragStart(node) {if(!node.data.is_edit_sort){return false} }, // 拖拽成功完成时触发的事件handleDrop(draggingNode, dropNode, dropType) {if(dropType == 'none') return // 准备排序参数可自行更改let params = {pk1: draggingNode.data.id,pk2: dropNode.data.id,direction:dropType == 'before' ? -1 : 1}this.orderClassify(params)}, /** *  拖拽时判定目标节点能否被放置。* @param {*} draggingNode * @param {*} dropNode * @param {*} type 参数有三种情况:'prev'、'inner' 和 'next',分别表示放置在目标节点前、插入至目标节点和放置在目标节点后*/allowDrop(draggingNode, dropNode, type) {if (draggingNode.level === dropNode.level) { if (draggingNode.data.parent_id === dropNode.data.parent_id && dropNode.data.is_edit_sort) {// 向上拖拽 || 向下拖拽return type === "prev" || type === "next"}} else {// 不同级进行处理return false}},//判断节点能否被拖拽allowDrag(draggingNode) {if(!draggingNode.data.is_edit_sort){return false}return true }, async orderClassify(params){// 发送排序请求}, setClassCofig(flag,id,title,value){this.classifyCofig['flag'] = flagthis.classifyCofig['Id'] = idthis.classifyCofig['title'] = titlethis.classifyCofig['value'] = value},openClassify(pid,txt){this.setClassCofig(true,pid, txt ? txt : '新增分类','')   },editClassify(row){this.setClassCofig(true,row.id, '修改分类', row.name) }, closeAdd(){this.setClassCofig(false,'', '', '')},// 新增/修改分类async sureClassify(params){ let {value,Id} = this.classifyCofig// 通过value的值判断当前是新增还是修改// 刷新分类,cid 新分类的idlet refresh = { }if(value){ refresh.flag = false}else{ refresh.flag = true}  // 准备参数,发送请求// 请求成功后执行this.setClassCofig(false,'', '', '')refresh.cid = value? this.checkedId : res.data.data.idthis.$emit('refreshClass',refresh)},//判断分类是否可以删除async delBefore(id,pid){//1.自定义判断是否可以删除,//2.可以删去执行删除操作,this.sureDelete(id,pid)},//删除分类,删除后回到上一级async sureDelete(id,pid){//1.准备删除的接口使用数据//2.发起请求,请求成功后执行下面代码this.setClassCofig(false,'', '', '')let refresh = {flag: true,cid: pid}this.$emit('refreshClass',refresh)},}};
</script>

使用tree组件

  • html
 <PersonalTree :activeId="currentClassfiyId" :classifyData="classifyData"@selectId="changeSelectId" @selectaddId="setAddId" @refreshClass="refreshClass"/>
  • js
<script>
// 在此处引入tree组件命名为customTreeexport default{components:{customTree},data(){return{currentClassfiyId:'',addClassifyId:[],classifyData:[], }},mounted(){this.getClassList(true) },methods:{async getClassList(flagScene,cid){// console.log(flagScene,cid)// 发送请求,获取全部分类this.classifyData = res.data.data.classify this.currentClassfiyId = cid || this.classifyData?.[0].idif(flagScene){ // 可以去获取内容} }},refreshClass({flag,cid}){// 去刷新分类列表this.getClassList(flag,cid)},setAddId(val){this.addClassifyId = val},changeSelectId(id){this.currentClassfiyId = id// 可以去获取内容},}}
</script>   

classifyData的数据:

[{"id": 1033,"name": "一级分类","parent_id": 0, "level": 1,"child": [{"id": 1036,"name": "aaaaaaaaa","parent_id": 1033, "level": 2,"child": [],"is_edit_sort": true,"is_add_classify": true,"is_add_scene": true},{"id": 1035,"name": "aaaaa","parent_id": 1033,  "level": 2,"child": [{"id": 1037,"name": "a-1","parent_id": 1035, "level": 3,"child": [{"id": 1040,"name": "a-1-3","parent_id": 1037, "level": 4,"child": [],"is_edit_sort": true,"is_add_classify": false,"is_add_scene": true},{"id": 1038,"name": "a-1-1","parent_id": 1037, "level": 4,"child": [],"is_edit_sort": true,"is_add_classify": false,"is_add_scene": true}],"is_edit_sort": true,"is_add_classify": true,"is_add_scene": true}],"is_edit_sort": true,"is_add_classify": true,"is_add_scene": true}],"is_edit_sort": true,"is_add_classify": true,"is_add_scene": true
},{"id": 1032,"name": "测试分类b","parent_id": 0, "level": 1,"child": [],"is_edit_sort": true,"is_add_classify": true,"is_add_scene": true
},{"id": 1015,"name": "无操作区","parent_id": 0,"level": 1,"child": [],"is_edit_sort": false,"is_add_classify": false,"is_add_scene": false
}]

如有帮到您,请收藏+关注哦!!!

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

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

相关文章

C语言——switch语句判断星期

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int day 0;scanf("请输入1-7之间的整数&#xff1a;%d",&day);switch(day){case 1:printf("星期一\n");break;case 2:printf("星期二\n");break;case 3:printf(&quo…

Java基于springboot开发的景点旅游项目

演示视频 https://www.bilibili.com/video/BV1cj411Y7UK/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 主要功能&#xff1a;用户可浏览搜索旅游景点&#xff08;分为收费和免费景点&#xff09;&#xff0c;购票&#xff08;支持多规格套餐购票&am…

【Node.js入门之—1.1Node.js 简介】

Node.js入门之—1.1Node.js 简介 文章目录 Node.js入门之—1.1Node.js 简介什么是 Node.js错误说法 Node.js 的特点跨平台三方类库自带http服务器非阻塞I/O事件驱动单线程 Node.js 的应用场合适合用Node.js的场合不适合用Node.js的场合弥补Node.js不足的解决方案 什么是 Node.j…

cordova Xcode打包ios以及发布流程(ionic3适用)

第一步 1、申请iOS证书 2、导入证书到钥匙串 第二步 1、xcode配置iOS证书 1.1用Xcode打开你的项目&#xff08;我的Xcode版本是新版&#xff09; 修改如下图 回到基本信息设置界面&#xff0c;Bundie 这项填写&#xff0c;最先创建的那个appid&#xff0c;跟创建iOS描述文件时选…

决策式AI与生成式AI

人工智能中深度学习&#xff0c;是一种受人脑的生物神经网络机制启发&#xff0c;并模仿人脑来解释、处理数据的机器学习技术&#xff0c;它能自动对数据进行特征提取、识别、决策和生成。它可以从不同的维度进行划分&#xff0c;如果按模型的特点来划分可分为决策式AI和生成式…

2023年中国金融控股公司研究报告

第一章 行业概况 1.1 定义 金融控股公司这一术语最初源自美国&#xff0c;特别是在美国的《金融服务法案》关于银行控股公司组织结构的条文中&#xff0c;首次出现了“金融控股公司”&#xff08;Financial Holding Company&#xff09;这一法律术语&#xff0c;尽管法案中并…

红黑数原理及存在原因

我红黑树那么牛&#xff0c;你们为什么不用&#xff1f;_哔哩哔哩_bilibili 面试时经常会被问到红黑树&#xff0c;它到底有什么优点呢&#xff1f; 对于查找数据&#xff0c;数组二分查询速度最快&#xff0c;时间复杂度为O(logN)。但是如果增加和删除数据&#xff0c;数组就…

ARMday02(汇编语法、汇编指令)

汇编语法 汇编文件中的内容 1.伪操作&#xff1a;在汇编程序中不占用存储空间&#xff0c;但是可以在程序编译时起到引导和标识作用 .text .global .glbal .if .else .endif .data .word.... 2.汇编指令&#xff1a;每一条汇编指令都用来标识一个机器码&#xff0c;让计算机做…

深度学习中的数据类型介绍:FP32, FP16, TF32, BF16, Int16, Int8 ...

文章目录 0. 前言1. 数据的存储方式2. 不同数据类型介绍2.1 深度学习中常用的数据类型2.2 BF16 类型的优势2.3 不同数据类型的使用场景 0. 前言 相比于 CPU&#xff0c;GPU 在架构设计时将更多的晶体管用于数据处理&#xff0c;而不是数据缓存和流量控制&#xff0c;因此可以高…

致:CSGO游戏搬砖人的一封信

最近大家还在坚持操作CSGO游戏搬砖项目不&#xff1f; 这个项目虽是稳赚项目&#xff0c;但也有行情好和行情不好的时候&#xff0c;平台的大中小各种活动的举办&#xff0c;都会对我们的项目造成一定影响。行情的上下波动势必然会影响卡价的波动&#xff0c;影响选品的快慢&a…

棱镜七彩亮相工控中国大会,以软件供应链安全助力新型工业化高质量发展

2023年11月1日-3日&#xff0c;2023第三届工控中国大会在苏州国际会议中心举办&#xff0c;本届大会由中国电子信息产业发展研究院、中国工业经济联合会、国家智能制造专家委员会、国家产业基础专家委员会、江苏省工业和信息化厅、江苏省国有资产监督管理委员会、苏州市人民政府…

HTML 表格

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>表格标签</title>/* <style>.yun {widt…

C++学习 --函数

目录 1&#xff0c; 函数定义 1-1&#xff0c; 有返回值 1-2&#xff0c; 无返回值 2&#xff0c; 函数声明 3&#xff0c; 函数分文件编写 3-1&#xff0c; 创建自定义头文件 3-2&#xff0c; 创建源文件 3-3&#xff0c; 自定义头文件中编写函数声明 3-4&#xff0c…

北京陪诊小程序|陪诊系统开发|陪诊小程序未来发展不可小觑

近几年随着互联网快速发展&#xff0c;各行业领域都比较注重线上服务系统&#xff0c;通过陪诊小程序开发可以满足更多用户使用需求&#xff0c;同时还能提高用户使用体验。现在陪诊类的软件应用得到全面推广&#xff0c;在医疗行业当中陪诊小程序更贴近用户生活&#xff0c;可…

【漏洞复现】Apache_Tomcat7+ 弱口令 后台getshell漏洞

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 说明内容漏洞编号漏洞名称Tomcat7 弱口令 && 后台getshell漏洞漏洞评级高…

掌动智能:功能测试及拨测主要功能

在企业中对于功能测试及拨测而言&#xff0c;用户只需提供应用包和产品文档&#xff0c;由资深测试专家设计并执行测试&#xff0c;覆盖核心场景&#xff0c;包含特定业务流程以及行业通用特殊场景&#xff0c;支持需求定制。 执行过程严格监控&#xff0c;依据应用功能和业务需…

8年资深测试总结,接口自动化框架的设计与实现,一文打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、自动化测试框架…

Ionic 模块组件的理解

1 Ionic4.x 文件分析 1.1 app.module.ts 分析 Ionic 是一个基于 Angular 的移动应用开发框架&#xff0c;能帮助开发者使用 Web 技术&#xff08;HTML5、CSS3、JavaScript&#xff09;创建跨平台的应用程序。在 Ionic 应用程序中&#xff0c;app.module.ts 文件是整个应用程序的…

基于javaweb+mysql的jsp+servlet学生成绩管理系统(管理员、教师、学生)

博主24h在线&#xff0c;想要源码文档部署视频直接私聊&#xff0c;9.9元拿走&#xff01; 基于javawebmysql的jspservlet学生成绩管理系统(管理员、教师、学生)(javajspservletjavabeanmysqltomcat) 运行环境 Java≥8、MySQL≥5.7、Tomcat≥8 开发工具 eclipse/idea/myecl…

UE5 c++将自定义UserWdiget添加到对应菜单栏

前言&#xff1a; 为了实现与UserWidget一致的右键添加&#xff0c;便有了此章 注&#xff1a;这里使用的是UE5.3 目标内容&#xff1a; 这里可以参考UserWidget的源码&#xff0c;拷贝一份属于自己的就ok&#xff08;本篇章只是全改成了属于自己的CommonUserWidget&#xff…