Vue:eliment-ui el-tree动态加载更新
最近在数据源管理功能,需要以树的形式异步展现:
根节点可以新增目录。
目录节点可以新增目录,编辑目录,新增主数据。
主数据节点无操作按钮。
找到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