分析
- 增加(修改)根节点
- 增加(修改)叶子节点
- 懒加载叶子节点
DOM结构
<el-button
icon="el-icon-refresh-left"
size="mini"
type="warning"
@click="addRootTree()"
>添加根节点
</el-button>
<el-tree
ref="tree"
:data="projectList"
:expand-on-click-node="false"
:load="loadProjectNode"
:props="defaultProps"
lazy
node-key="id"
>
<template v-slot="{ node, data }">
<span class="custom-tree-node">
<el-popover
v-if="data.isShowSpan"
placement="top-start"
popper-class="poject-tree-el-popover"
trigger="hover"
>
<el-button
v-permission="permission.add"
size="mini"
type="text"
@click="handleAdd(node,data)"
>
新增
</el-button>
<el-button
v-permission="permission.edit"
size="mini"
type="text"
@click="handleEdit(data)"
>编辑
</el-button>
<el-popconfirm
style="margin-left: 10px;"
title="确定要删除这个目录吗?"
@confirm="doDelete(node,data)"
>
<el-button
slot="reference"
v-permission="permission.del"
size="mini"
type="text"
>
删除
</el-button>
</el-popconfirm>
<span slot="reference" class="node-label">{{ data.name }}</span>
</el-popover>
<template v-else>
<el-input
ref="inputValue"
v-model="inputValue"
class="node-input"
placeholder="请输入内容"
style="width: 150px; margin-right: 10px;"
@keyup.enter.native="saveNewNode(node, data)"
/>
<el-button
circle
icon="el-icon-check"
size="mini"
style="padding: 4px"
type="success"
@click="saveNewNode(node,data)"
/>
<el-button
v-if="!data.id"
circle
icon="el-icon-delete"
size="mini"
style="padding: 4px"
type="danger"
@click="deleteNewNode(node,data)"
/>
</template>
</span>
</template>
</el-tree>
js实现
// data中的数据
projectList:[],
newChild: {
name: '',
label: '',
children: [],
isShowSpan: false, // 为了区分是输入框状态还是span标签状态
leaf: true,
id: '',
type: '' // 1:代表根节点 2:代表叶子节点 3:代表编辑
},
defaultProps: {
isLeaf: 'leaf',
children: 'children', // 子节点字段名
label: 'label' // 节点文本字段名
}
editInfo: {},
inputValue: '',
// 功能函数---添加根节点
addRootTree() {
const canAddNewNode = this.justShowInput();
if (!canAddNewNode) {
const newChild = { ...this.newChild, type: '1' };
this.projectList.unshift(newChild)
this.inputFocus();
}
}
// 功能函数---添加叶子节点
handleAdd(node, data) {
const canAddNewNode = this.justShowInput();
if (!canAddNewNode) {
this.$set(data, 'hasChildren', true);
this.$set(data, 'noFistLoad', true);
node.loaded = false;
node.expand();
}
}
// 功能函数---修改节点
handleEdit(data) {
const canAddNewNode = this.justShowInput();
if (!canAddNewNode) {
data.type = '3'
data.isShowSpan = false;
this.inputValue = data.name
this.editInfo = data;
this.inputFocus();
}
}
// 功能函数---删除没有id的节点
deleteNode(node, data) {
this.showInput = false;
this.inputValue = '';
this.$refs.tree.remove(node)
}
// 功能函数---删除有id的节点
doDelete(node, data) {
// 走自己的接口进行删除 然后进行以下操作
this.updateNode(node)
}
// 功能函数---懒加载函数
loadProjectNode(node, resolve) {
setTimeout(() => {
getPmTreeSmall(params).then(res => {
if (resolve) {
const data = this.addIsShowSpan(res.content);
if (node.data.noFistLoad) {
const newChild = { ...this.newChild, type: '2', data: node.data };
data.unshift(newChild)
setTimeout(() => {
this.inputFocus();
}, 100)
}
resolve(data)
} else {
this.projectList = this.addIsShowSpan(res.content)
}
})
}, 100)
},
// 功能函数---保存节点
saveNewNode(node, data) {
// 走接口 保存或者编辑 成功之后
// 1. 接口没有返回值
this.updateNode(node);
// 2. 接口有返回值为res
this.$set(data, 'isShowSpan', true);
Object.keys(res).forEach(key => {
this.$set(data, key, res[key]);
});
this.inputValue = '';
this.showInput = false;
},
// 辅助函数---通过接口更新数据
updateNode() {
this.inputValue = ''
this.$set(node.parent.data, 'noFistLoad', false);
node.parent.loaded = false;
node.parent.expand();
}
// 辅助函数---获取到数据之后进行添加isShowSpan
addIsShowSpan(data) {
return data.map(item => {
item.isShowSpan = true;
return item;
});
}
// 辅助函数---输入框显示的时候立刻获取焦点
async inputFocus() {
await this.$nextTick()
const inputElement = this.$refs.inputValue
inputElement.focus()
}
// 辅助函数---判断当前是否存在输入框
justShowInput() {
if (this.showInput) {
this.$notify({
title: '还有未保存的目录',
type: 'info',
duration: 2500
})
return true; // 阻止添加新节点并触发通知
} else {
this.showInput = true;
return false; // 允许添加新节点
}
}
希望有所帮助!!!也希望掘友们能提出意见