程序员不易,且干且珍惜!
后管项目中,树形图是我们经常用到的一个组件,很多还要求用户可以编辑,增删改查子级。原来一直都是着急忙慌的写上该功能,现在终于有时间整理一下了。
其实,百度上有很多该功能的实现方法,提供给我们开发过程中借鉴,我也尝试过不同的写法,有的效果不佳,有的已经不能用了,本篇文章,是我总结后的自认为比较好用的,我以后遇到此类的需求就可以直接用,在这里,也算是记录一下:
1,实现效果和逻辑
效果:树结构未操作时,所有层级展开,操作按钮隐藏;鼠标移入某层级,该层级显示要求的操作按钮,比如:最后一层级不可添加,其他层级可以增删改。
逻辑:实现树结构可以编辑主要思想就是 - 树结构开启可自定义模式,操作某一层级的时候显示不同的内容(其实也就是不同的操作按钮和输入框),在我们操作结束时,将更改数据存入后端,完成增删改功能,树结构刷新。
2,效果图
未编辑状态 编辑状态:
** 3,实现代码**
<template>
<div class="type-tree">
/
*
*typeData: 树结构数据
*defaultProps:树结构层级配置项
*default-expand-all:默认展开所有层级
*:expand-on-click-node="false":关闭层级默认点击方法(点击收缩展开层级)
*@node-click="handleNodeClick":自定义层级点击方法
*slot-scope="{ node, data }":开启层级内容自定模式
*@mouseenter="mouseenter(data)":鼠标移入某层级方法:改变数据的del变量值,控制操作图标显示
*@mouseleave="mouseleave(data)":鼠标移入某层级方法:改变数据的del变量值,控制操作图标隐藏
*
/
<el-tree
:data="typeData"
:props="defaultProps"
node-key="id"
default-expand-all
:expand-on-click-node="false"
@node-click="handleNodeClick">
<div slot-scope="{ node, data }" @mouseenter="mouseenter(data)" @mouseleave="mouseleave(data)" style="width: 100%;">
<div>
<!-- 不可编辑情况 -->
<span v-if="data.id != operationVis" class="custom-tree-node">
<span style="width: 50%;display: inline-block;">{{ node.label }} <el-button type="text" icon="el-icon-plus" v-show="node.level === 1" @click="() => append(node, data)"></el-button></span>
<span>
<!-- 编辑 -->
<el-button
type="text"
size="mini"
icon="el-icon-edit"
style="color: #53D06B;padding: 3px;"
v-show="node.level !== 1 && data.del"
@click="() => edit(node, data)">
</el-button>
<!-- 删除 -->
<el-button
type="text"
size="mini"
icon="el-icon-delete"
style="color:#FD7474;padding: 3px;"
v-show="node.level !== 1 && data.del"
@click="() => remove(node, data)">
</el-button>
<!-- 添加 -->
<el-button
type="text"
size="mini"
icon="el-icon-plus"
style="color:#39A1FF;padding: 3px;"
v-show="(node.level === 2 || node.level === 3) && data.del"
@click="() => append(node, data)">
</el-button>
</span>
</span>
<!-- 可编辑情况 -->
<span v-else class="custom-tree-node">
<input
style="width: 50%"
size="mini"
ref="inputVal"
:value="data.name"
placeholder="请输入分类名"
@change="nameChange(data,$event)"
/>
<span>
<!-- 编辑确认 -->
<el-button
type="text"
size="mini"
icon="el-icon-circle-check"
style="color: #53D06B;padding: 3px;"
@click="() => checkOK(node, data)">
</el-button>
<!-- 编辑取消 -->
<el-button
type="text"
size="mini"
icon="el-icon-circle-close"
style="padding: 3px;"
@click="() => checkCancel(node, data)">
</el-button>
</span>
</span>
</div>
</div>
</el-tree>
</div>
</template>
<script>
import { getBigKindsTree, saveBigKinds, deleteBigKinds } from '@/api/equipment/equipmentType.js';
export default {
data(){
return {
defaultProps: {
children: 'subregion',
label: 'name'
},
typeData: [{
id: '0',
name: '全部设备',
subregion: []
}],
// 编辑选中的节点
operationVis: '',
}
},
created(){
this.getTreeData()
},
mounted(){},
methods:{
handleNodeClick(data){
this.$emit('nodeClickData',data)
},
mouseenter(data){
this.$set(data, 'del', true)
},
mouseleave(data){
this.$set(data, 'del', false)
},
// tree 获取设备大类数据
getTreeData() {
getBigKindsTree()
.then(res => {
if(res.data && res.data.code === 0){
this.typeData[0].subregion = res.data.data
}else {
this.$message.error('设备分类数据获取失败')
}
})
.catch((err) => {
this.$message.error(err.message)
})
},
// 树结构编辑方法:将操作的层级ID赋值给operationVis,显示编辑状态下的HTML内容
edit(node, data){
this.operationVis = data.id
},
// 树结构删除方法:删除选中层级
remove(node, data){
let deleteParams = []
deleteParams.push(data.id)
deleteBigKinds(deleteParams)
.then(res => {
if(res.data && res.data.code === 0){
this.$message({
message: '删除成功',
type: 'success',
})
}else{
this.$message.error(res.data.msg || '操作失败')
}
})
.catch((err) => {
this.$message.error(err.msg)
}).finally(() => {
this.getTreeData()
})
},
// 树结构新增方法:在该增加下新增一个子层级,新增的层级在第一个
append(node, data){
let num = new Date().getTime()
let newChild = { id: '' + num, name: '', parentId: data.id, editFlag: '1', subregion: [] }
if (!data.subregion) {
this.$set(data, 'subregion', []);
}
data.subregion.unshift(newChild);
this.operationVis = newChild.id
},
// tree 新增/编辑确定方法:将新增的层级信息传入后端
checkOK(node, data){
// 分类名不填写时,不能正常添加和编辑分类
if(data && data.editFlag == '1' && !data.label) {
this.$message.error('操作失败, 分类名称不能为空')
this.checkCancel()
return false
}
if(data && data.editFlag == '1'){
let appendParams = {
parentId: data.parentId,
name: data.label,
subregion: []
}
saveBigKinds(appendParams)
.then(res => {
if(res.data && res.data.code === 0){
this.$message({
message: '新增操作成功',
type: 'success',
})
}else{
this.$message.error(data.msg || '操作失败')
}
})
.catch((err) => {
this.$message.error(err.message)
}).finally(() => {
this.getTreeData()
})
}else{
let editParams = {
id: data.id,
parentId: data.parentId,
name: data.label,
}
saveBigKinds(editParams)
.then(res => {
if(res.data && res.data.code === 0){
this.$message({
message: '修改操作成功',
type: 'success',
})
}else{
this.$message.error(data.msg || '操作失败')
}
})
.catch((err) => {
this.$message.error(err.message)
}).finally(() => {
this.getTreeData()
})
}
this.operationVis = ""
},
// tree 编辑取消
checkCancel(){
this.operationVis = ""
this.getTreeData()
},
// 树结构编辑状态下,输入框内容写入该层级的数据中
nameChange(data,e){
data.label = e.target.value;
}
}
}
</script>
<style lang="scss" scoped>
.custom-tree-node{
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>
该功能就记录到这里,有需要的小伙伴可以直接拿去使用,一般情况下不会有问题,嘎嘎好用!
拜了个拜,迪迦。。。
版权归原作者 清狂无益 所有, 如有侵权,请联系我们删除。