前言
在最近的一个项目中,有一个组织树的需求,因为数据量比较大,要求懒加载并且能够在树上对组织进行操作,项目使用的是vue+ElementUI。ElementUI中有个el-tree,正好可以拿来用。项目引入ElementUI什么的就不说了,大家都知道,直接使用el-tree实现需求吧。
上代码
首先看下ElementUI中关于el-tree懒加载的介绍
关键的就是load和lazy属性,于是开始写代码
template中:
<el-tree :props="props" :highlight-current="true" lazy :load="loadNode" :expand-on-click-node="false" ref="tree"></el-tree>
data中:
props: { label: "orgName", isLeaf: "leafed" },
methods中:
loadNode(node, resolve) { // 加载子树数据的方法 if (node.level === 0) { // parentNodeItem是自定义的根节点 const item = this.parentNodeItem; return resolve([ { orgName: item.orgName, orgId: item.orgId } ]); } else { // 调用接口获取数据 this.getOrgList({ params: { orgId: node.data.orgId }, callback: res => { resolve(res.data); } }); } },
效果(点击播放观看):
接下来要实现动态增删改,因为要把操作放到树上,最先想到的就是把按钮放到节点的后边,使用render-content来实现,修改之前的代码:
<el-tree :props="props" :highlight-current="true" lazy :load="loadNode" :expand-on-click-node="false" ref="tree" :render-content="renderContent"></el-tree>
methods中:
renderContent(h, { node, data, store }) { // 树节点的内容区的渲染 // 设置display为none是先隐藏所有的按钮,当鼠标移上节点的时候才显示出来 // $event是为了阻止事件冒泡,点击按钮的时候不会选中该节点 // 因为在项目中树是作为一个子组件的,所有这里用了$emit return ( <span class="custom-tree-node"> <span>{node.label}</span> <span class="operation" style="display: none"> <el-button icon="el-icon-plus" size="mini" type="text" on-click={($event) => this.$emit('add',$event, node, data)}></el-button> <el-button icon="el-icon-edit" size="mini" type="text" on-click={($event) => this.$emit('update',$event, node, data)}></el-button> <el-button icon="el-icon-delete" size="mini" type="text" on-click={($event) => this.$emit('delete',$event, node, data)}></el-button> </span> </span> ); }
父组件中style:
/deep/.custom-tree-node { .operation { display: none; } &:hover { .operation { margin-left: 10px; display: inline !important; } } }
看下效果(点击播放观看):
接下来就是重点了,要实现动态增删改:
1、增 和 改
因为增加节点和修改节点用到同一个弹窗和表单,所以放到一起讲了
在父组件中监听子组件emit的事件:
父组件的template中:
<!--OrgTree就是父组件中引的tree组件--> <OrgTree ref="orgTree" @add="handleAddOrg" @update="handleUpdateOrg" @delete="handleDeleteOrg"></OrgTree>
父组件的methods中:
重要的代码加粗加色了
// 添加子组织 handleAddOrg(event, node, data) { // 下面这行就是阻止事件冒泡 event.cancelBubble = true; this.currentOrg = data; // 保存当前要增加组织的节点,这个很重要 this.currentNode = node; this.editOrgForm.orgName = ""; this.orgModalTitle = "添加组织"; this.orgModalType = "add"; this.isOrgModalVisible = true; }, // 更新组织 handleUpdateOrg(event, node, data) { event.cancelBubble = true; this.currentOrg = data; this.editOrgForm.orgName = data.orgName; this.orgModalTitle = "修改组织"; this.orgModalType = "edit"; // 保存当前组织的节点和数据, 这个很重要 this.currentNode = node; this.currentNodeData = data; // 保存当前组织的父节点,这个很重要 this.parentNode = node.parent; this.isOrgModalVisible = true; // 没有写注释的就是和本次要讲的内容没太大关系,无非就是让弹窗显示、把已有的组织名显示在弹窗里 },
提交表单:
// 提交组织表单 handleOrgConfirm(form) { // 表单验证 this.$refs[form].validate(valid => { if (valid) { // 如果是添加组织,先向后台发起请求 if (this.orgModalType === "add") { this.addOrg({ params: { parentId: this.currentOrg.orgId, orgName: this.editOrgForm.orgName }, callback: res => { if (res.resultCode === "200") { // 如果后台添加成功,后台会返回添加组织的id,把id和组织名封装起来 this.isOrgModalVisible = false; const nodeData = { orgName: this.editOrgForm.orgName, orgId: res.data.orgId }; // 通过append方法将封装好的节点拼接到之前保存的节点 this.$refs.orgTree.$refs.tree.append( nodeData, this.currentNode ); this.$message.success("添加组织成功"); } } }); } else { // 如果是修改组织 this.updateOrg({ params: { orgId: this.currentOrg.orgId, orgName: this.editOrgForm.orgName }, callback: res => { // 先向后台发起修改请求,如果修改成功了 if (res.resultCode === "200") { this.isOrgModalVisible = false; // 就把原来的节点移除掉 this.$refs.orgTree.$refs.tree.remove( this.currentNode, this.currentNodeData ); // 然后把新的组织名和id封装起来 const newNodeData = { orgId: this.currentOrg.orgId, orgName: this.editOrgForm.orgName }; // 把封装的节点拼接起到之前保存的父节点下,这样就不需要刷新整棵树 this.$refs.orgTree.$refs.tree.append( newNodeData, this.parentNode ); this.$message.success("修改组织成功"); } } }); } } }); },
然后就是删除组织了,这个比较简单了
// 删除组织 handleDeleteOrg(event, node, data) { event.cancelBubble = true; this.$confirm("确定删除该组织?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(() => { this.deleteOrg({ params: { orgId: data.orgId }, callback: res => { if (res.resultCode === "200") { // 首先调用接口,后台移除成功了才将其移除掉 this.$refs.orgTree.$refs.tree.remove(node, data); this.$message.success("删除组织成功"); } } }); }).catch(() => { }); },
看下效果(点击播放查看效果):
这样就实现了。如果大家还有更好的方法一起交流下?。
所有评论(0)