最近在数据源管理功能,需要以树的形式异步展现:
根节点可以新增目录。
目录节点可以新增目录,编辑目录,新增主数据。
主数据节点无操作按钮。
找到element-ui的官方文档,el-tree。(地址:http://element-cn.eleme.io/#/zh-CN/component/tree )
结合自定义节点内容:
1.节点后添加操作按钮
renderContent(h, { node, data }) {
return (
<span class="custom-tree-node">
<span>{node.label}</span>
<span>
<i
v-show={
node.level == 1 || data.nodeType == FunctionNodeType.BizFolder
}
class="el-icon-plus"
title="新增目录"
on-click={() => this.editBizFolder(node, "add", resolve)}
/>
<i
v-show={data.nodeType == FunctionNodeType.BizFolder}
class="el-icon-edit"
title="编辑目录"
on-click={() => this.editBizFolder(node, "edit")}
/>
<i
v-show={data.nodeType == FunctionNodeType.BizFolder}
class="el-icon-document"
title="添加主数据"
on-click={() => this.addBizObject(node)}
/>
</span>
</span>
);
}
2. 默认根节点是展开的
<el-tree
:data="data"
:props="defaultProps"
:highlight-current="true"
:load="loadDataTree"
lazy
:expand-on-click-node="false"
:render-content="renderContent"
node-key="id"
:default-expanded-keys="['1']"
@node-click="nodeClick"
></el-tree>
标红处为关键代码
3. 动态添加,更新后刷新节点
append方法肯定是不行的,添加完成后,需要重新拉取查询子节点的接口,这个方法放弃了,
缓存resolve方法,这个方法也是不可取的,this的指向会发生问题(展开节点a再点击b节点的新增目录),这个方法也必须得放弃。
element-ui提供了 doCreateChildren(children, defaultProps)方法创建子节点
children就是你需要动态添加的数据。
reloadNode(node) {
DataSourceService.getDataTree(node.data.objectId).then(
res => {
if (res.data && res.data.length > 0) {
let rootChildren = [];
res.data.forEach(element => {
rootChildren.push({
name: element.Text,
leaf: element.IsLeaf,
objectId: element.ObjectID,
code: element.Code,
nodeType: element.NodeType,
sortKey: element.SortKey,
children: []
});
});
node.childNodes = []; //清空节点
node.doCreateChildren(rootChildren); //更新节点
}
}
)
4.最终代码
<!-- 外部数据源 -->
<template>
<div id="master-data">
<div class="master-data-tree">
<el-tree
:data="data"
:props="defaultProps"
:highlight-current="true"
:load="loadDataTree"
lazy
:expand-on-click-node="false"
:render-content="renderContent"
node-key="id"
:default-expanded-keys="['1']"
@node-click="nodeClick"
></el-tree>
</div>
<div class="master-data-info">
</div>
</div>
</template>
<script>
import DataSourceService from "@/services/data-source.service";
import FunctionNodeType from "@/models/data-source/function-node-type.js";
export default {
name: "master-data",
data() {
return {
defaultProps: {
children: "children",
label: "name",
isLeaf: "leaf"
}
};
},
components: {
},
computed: {},
methods: {
loadDataTree(node, resolve) {
if (node.level === 0) {
return resolve([{ id: "1", name: "主数据", objectId: "" }]);
}
DataSourceService.getDataTree(node.data.objectId).then(
res => {
if (!res.status) {
return;
}
let rootChildren = [];
if (res.data && res.data.length > 0) {
res.data.forEach(element => {
rootChildren.push({
name: element.Text,
leaf: element.IsLeaf,
objectId: element.ObjectID,
code: element.Code,
nodeType: element.NodeType,
sortKey: element.SortKey,
children: []
});
});
}
if (resolve) {
resolve(rootChildren); //动态加载时
} else {
//更新节点时:
node.childNodes = [];
node.doCreateChildren(rootChildren);
}
}
);
},
renderContent(h, { node, data }) {
return (
<span class="custom-tree-node">
<span>{node.label}</span>
<span>
<i
v-show={
node.level == 1 || data.nodeType == FunctionNodeType.BizFolder
}
class="el-icon-plus"
title="新增目录"
on-click={() => this.editBizFolder(node, "add", resolve)}
/>
<i
v-show={data.nodeType == FunctionNodeType.BizFolder}
class="el-icon-edit"
title="编辑目录"
on-click={() => this.editBizFolder(node, "edit")}
/>
<i
v-show={data.nodeType == FunctionNodeType.BizFolder}
class="el-icon-document"
title="添加主数据"
on-click={() => this.addBizObject(node)}
/>
</span>
</span>
);
},
editBizFolder(node, type) {
// 新增编辑目录
event.stopPropagation(); // 阻止冒泡给nodeClick
const data = node.data;
const parentData = node.parent.data;
const title = type == "add" ? "新增目录" : "编辑目录";
//...弹窗逻辑,保存后回调
const refreshNode = type == "add" ? node : node.parent;
this.loadDataTree(refreshNode); //刷新节点
},
nodeClick(data) {
debugger;
// 点击树
}
}
};
</script>
<style>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.custom-tree-node i {
margin-left: 10px;
}
#master-data {
height: 100%;
flex: 1;
flex-direction: row;
display: flex;
}
.master-data-tree {
width: 270px;
border-right: 1px solid #dcdfe6;
}
.master-data-info {
width: 100%;
margin-left: 20px;
}
</style>
另el-tree的一些基本方法...
(可参考element-ui源码node_modules\element-ui\packages\tree\src\model\node.js 和tree-store.js)
1.设置展开和收缩
if (!node.expanded) {
node.expand();
} else {
node.collapse();
}
2.获取父节点
node.parent