element ui tree树形控件 编辑,新增及删除。效果图如下:
可实现对一、二、三级目录的增删改,以及页面样式实现。

<template>代码
<template> <div> <!-- 导航菜单 --> <div class="custom-tree-container"> <div class="block"> <!-- <p>使用 scoped slot</p> --> <div class="allC" @click="handleAllCase"> <i class="el-icon-link"></i><span class="allCase">所有用例</span> </div> <el-tree :data="data" show-checkbox node-key="id" :expand-on-click-node="false" @node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave" @node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop" @node-click="myEvent" draggable :allow-drop="allowDrop" :allow-drag="allowDrag" > <span class="custom-tree-node" slot-scope="{ node, data }" @mouseenter="onMouseOver($event)" @mouseleave="onMouseOut($event)" > <span v-if="!data.isEdit">{{ node.label }}</span> <span class="isEdit"> <!-- 编辑状态 --> <div v-if="data.isEdit"> <el-input v-model="data.label" autofocus size="mini" :ref="'slotTreeInput' + data[id]" @blur.stop="handleInput(node, data)" @keyup.enter.native="handleInput(node, data)" ></el-input> </div> <!-- 非编辑状态 --> <div v-else> <!-- 名称: 新增节点增加class(is-new) --> <span :class="[ data[id] < NODE_ID_START ? 'is-new' : '', 'comp-tr-node--name', ]" > </span> </div> <span class="comp-tr-node--btns" v-show="false"> <el-dropdown trigger="click" @visible-change="handleDropdown"> <i class="el-icon-more"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item @click.native="() => append(node, data)"> <i class="el-icon-circle-plus-outline"></i >新增</el-dropdown-item > <el-dropdown-item @click.native="handleEdit(node, data)" ><i class="el-icon-edit"></i>编辑</el-dropdown-item > <el-dropdown-item @click.native="() => remove(node, data)" ><li class="el-icon-delete"></li> 删除</el-dropdown-item > </el-dropdown-menu> </el-dropdown> </span> </span> </span> </el-tree> <i class="el-icon-plus" ><span @click="handleNewMoudle">新建模块</span></i > </div> </div> </div> </template>
JS代码
<script>
let id = 1000;
export default {
data() {
const data = [
{
id: 1,
label: "用例管理",
children: [
{
id: 4,
label: "用例first",
children: [
{
id: 5,
label: "用例second",
},
{
id: 6,
label: "用例three",
},
],
},
],
},
{
id: 2,
label: "用例管理",
children: [
{
id: 7,
label: "用例first",
},
{
id: 8,
label: "用例second",
},
],
},
{
id: 3,
label: "用例管理",
children: [
{
id: 9,
label: "用例first",
},
{
id: 10,
label: "用例second",
},
],
},
];
return {
data: JSON.parse(JSON.stringify(data)),
currentEle: null, //操作下拉列表 当前图表元素 省略号
dropdownShow: false, //下拉列表当前显示状态
setTree: [], // tree数据
id: "id", // id对应字段
MAX_LEVEL: 3, // 设定最大层级
NODE_ID_START: 0, // 新增节点id,逐次递减
startId: null,
//页面可拖拽
defaultProps: {
children: "children",
label: "label",
},
};
},
props: {
bool: {
type: Boolean,
default: false,
},
},
created() {
// 初始值
this.startId = this.NODE_ID_START;
},
methods: {
//所有用例列表接口
handleAllCase() {},
//el-tree点击事件
myEvent(d1, d2, d3) {
this.$emit("myEvent", d1.id);
}, //d1.label
//下拉列表
handleDropdown(v) {
this.dropdownShow = v;
if (v) return;
this.currentEle.style.cssText += "display:none";
},
//增删改鼠标移入移出隐藏显示
//鼠标移入
onMouseOver: function (event) {
event.target.parentElement.querySelector(
".comp-tr-node--btns"
).style.cssText += "display:block";
this.currentEle = event.target.parentElement.querySelector(
".comp-tr-node--btns"
);
},
//鼠标移出
onMouseOut: function (event) {
if (this.dropdownShow) return;
event.target.parentElement.querySelector(
".comp-tr-node--btns"
).style.cssText += "display:none";
},
//新增一级目录模块点击事件
handleNewMoudle() {
this.data.push({
id: id++,
label: "未命名模块",
children: [],
isEdit: true,
});
},
//新增按钮
append(node, data) {
if (node.level >= this.MAX_LEVEL) {
this.$message.warning(
"当前目录已达到" + this.MAX_LEVEL + "级,无法新增!"
);
return false;
}
//新定义一个对象
const newChild = {
id: id++,
label: "未命名模块",
children: [],
isEdit: true,
};
if (!data.children) {
this.$set(data, "children", []);
}
data.children.push(newChild);
//新增子节点到3级
console.log(node, data);
this.$nextTick(() => {
if (this.$refs["slotTreeInput" + data[this.id]]) {
this.$refs["slotTreeInput" + data[this.id]].$refs.input.focus();
}
});
},
//删除按钮
remove(node, data) {
const parent = node.parent;
const children = parent.data.children || parent.data;
const index = children.findIndex((d) => d.id === data.id);
children.splice(index, 1);
},
//编辑按钮
handleInput(node, data) {
// 修改节点
console.log(node, data);
// 退出编辑状态
if (data.isEdit) {
this.$set(data, "isEdit", false);
}
},
handleEdit(node, data) {
// 编辑节点
console.log(node, data);
// 设置编辑状态
if (!data.isEdit) {
this.$set(data, "isEdit", true);
}
// 输入框聚焦
this.$nextTick(() => {
if (this.$refs["slotTreeInput" + data[this.id]]) {
this.$refs["slotTreeInput" + data[this.id]].$refs.input.focus();
}
});
},
//拖拽点击事件
handleDragStart(node, ev) {
// console.log("drag start", node);
},
handleDragEnter(draggingNode, dropNode, ev) {
//console.log("tree drag enter: ", dropNode.label);
},
handleDragLeave(draggingNode, dropNode, ev) {
// console.log("tree drag leave: ", dropNode.label);
},
handleDragOver(draggingNode, dropNode, ev) {
// console.log("tree drag over: ", dropNode.label);
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
// console.log("tree drag end: ", dropNode && dropNode.label, dropType);
},
handleDrop(draggingNode, dropNode, dropType, ev) {
// console.log("tree drop: ", dropNode.label, dropType);
},
//拖拽点击事件
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.label === "二级 3-1") {
return type !== "inner";
} else {
return true;
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf("三级 3-2-2") === -1;
},
},
};
</script>CSS代码
<style lang="less" scoped>
.allC {
margin-left: 21px;
margin-bottom: 5px;
i {
color: #c0c4cc;
}
.allCase {
margin-left: 8px;
color: #606266;
font-size: 14px;
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-tree {
height: 100%;
.isEdit {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.el-input {
width: 100px;
height: 5px;
}
}
}
.el-icon-plus {
margin: 10px 0 0 22px;
color: #606266;
font-size: 14px;
span {
margin-left: 10px;
font-size: 14px;
}
}
</style>版权声明:本文为yuhan___原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。