Vue.js - 使用Element-UI的tree组件实现可编辑树教程(双击编辑、新增、删除节点)
作者:hangge | 2024-08-23 08:27
树形图是我们项目经常用到的一个组件。本文将介绍如何利用 Element-UI 的 tree 组件实现一个可编辑的树形结构,通过简单的操作实现节点的新增、删除和编辑功能。
1,效果图
(1)点击“新增”按钮后,在选中节点下会新增一个输入框,输入内容回车后(或者失去焦点时)插入新的子节点。

(2)选中一个节点后点击“删除”按钮可以将选中节点删除:

(3)双击某个节点文字,该节点会变成一个文本输入框,输入新的内容回车后(或者失去焦点时)则会更新此节点名称。

2,样例代码
<template>
<div id="container">
<!-- 新增按钮 -->
<el-button type="primary" size="small" icon="el-icon-plus"
@click="addNode" :disabled="!this.selectedNode">新增</el-button>
<!-- 删除按钮 -->
<el-button type="danger" size="small" icon="el-icon-delete"
@click="delNode" :disabled="!this.selectedNode">删除</el-button>
<!-- 树组件 -->
<el-tree class="my-tree" :data="treeData" :props="defaultProps"
show-checkbox :default-expand-all="true"
highlight-current :expand-on-click-node="false"
@node-click="nodeClick" :render-content="renderContent">
</el-tree>
</div>
</template>
<script>
export default {
name: 'MyTree',
data() {
return {
treeData: [
{
id: 1,
name: "电子产品",
children: [
{
id: 2,
name: "电脑",
children: [
{
id: 3, name: "苹果笔记本", children: []
},
{
id: 4, name: "戴尔笔记本", children: []
}
]
},
{
id: 5,
name: "手机",
children: [
{
id: 6, name: "iPhone", children: []
},
{
id: 7, name: "三星Galaxy", children: []
}
]
}
]
},
{
id: 8,
name: "家具",
children: [
{
id: 9,
name: "椅子",
children: [
{
id: 10, name: "网易严选办公椅", children: []
}
]
}
]
}
],
defaultProps: {
children: 'children',
label: 'name'
},
selectedNode: null, // 当前选中的节点
editingNode: null, // 当前正在编辑的节点
}
},
methods: {
// 渲染树节点显示的内容
renderContent(h, { node, data }) {
if (this.editingNode === data) {
return (
<el-input
vModel={data.name}
size="mini"
onInput={(value) => this.handleInput(value, data)}
onChange={() => this.handleBlur(data)}
nativeOnDblclick={(event) => event.stopPropagation()}
/>
);
} else {
return (
<span onDblclick={() => this.handleNodeDblClick(data)}>
{data.name}
</span>
);
}
},
// 树节点双击响应
handleNodeDblClick(data) {
// 至于区域层级双击有效
this.editingNode = data;
this.$nextTick(() => {
const input = this.$el.querySelector(`.tree .el-input input`);
if (input) {
input.focus();
}
});
},
// 树节点编辑状态下输入响应
handleInput(value, data) {
data.name = value;
},
// 树节点编辑状态下失去焦点响应
handleBlur(data) {
this.editingNode = null;
// 如果id不为空,则更新逻辑分组,否则新增逻辑分组
if (data.id) {
// this.doUpdate(data);
this.$notify({
title: '修改成功',
type: 'success'
});
} else {
// this.doAdd(data);
this.$notify({
title: '新增成功',
type: 'success'
});
}
},
// 树节点单击响应
nodeClick(data, node) {
this.selectedNode = data;
if(this.selectedNode != this.editingNode) {
this.editingNode = null;
}
},
// 新增节点
addNode() {
let item = {
"children": [],
"name": "",
"id": ""
}
this.editingNode = item
this.selectedNode.children.push(item);
this.$nextTick(() => {
const input = this.$el.querySelector(`.tree .el-input input`);
if (input) {
input.focus();
}
});
},
// 删除节点
delNode() {
for(let node of this.treeData) {
this.recursionDelNode(node)
}
// 弹出提示消息
this.$notify({
title: '删除成功',
type: 'success'
});
},
// 递归删除节点
recursionDelNode(node) {
if (node.children) {
node.children = node.children.filter(item => item !== this.selectedNode);
for(let child of node.children) {
this.recursionDelNode(child);
}
}
}
}
}
</script>
<style scoop>
#container {
padding: 20px;
}
.my-tree {
margin-top: 20px;
}
</style>
全部评论(0)