前言

在最近的一个项目中,有一个组织树的需求,因为数据量比较大,要求懒加载并且能够在树上对组织进行操作,项目使用的是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(() => { });
    },

看下效果(点击播放查看效果):

 这样就实现了。如果大家还有更好的方法一起交流下?。

转载于:https://www.cnblogs.com/shmily1213/p/11458109.html

Logo

前往低代码交流专区

更多推荐