element-ui实现树的拖拽及树节点的增删改查

这篇文章展示了如何使用Vue.js和ElementUI库创建一个具有拖放功能的树形组件,支持节点的添加、删除、编辑和拖拽排序。用户可以添加顶级节点,编辑节点名称,以及通过拖放操作改变节点结构。同时,组件还提供了输入验证和操作确认功能,确保用户交互的完整性和安全性。
摘要由CSDN通过智能技术生成

代码如下

界面效果

界面代码:

<el-button class="comp-tr-top" type="primary" size="small" @click="handleAddTop">添加顶级节点</el-button>
      <div class="treenode-container">
        <el-tree
          :data="deptOptions"
          :props="defaultProps"
          :expand-on-click-node="false"
          ref="tree"
          class="flow-tree"
          default-expand-all
          @node-drag-start="handleDragStart"
          @node-drag-enter="handleDragEnter"
          @node-drag-leave="handleDragLeave"
          @node-drag-over="handleDragOver"
          @node-drag-end="handleDragEnd"
          @node-drop="handleDrop"
          draggable
          @node-click="handleTreeNodeClick"
        >
          <template slot-scope="{ node, data }">
            <div :id="node.id" class="custom-tree-node">
              <template v-if="data.isHead">
                <el-input
                  v-model="data.name"
                  autofocus
                  size="mini"
                  :ref="'slotTreeInputHead'"
                  @blur.stop="handleHeadAdd(node, data)"
                  @keyup.enter.native="$event.target.blur()"
                ></el-input>
              </template>
              <template v-if="data.isAdd && !data.isHead">
                <el-input
                  v-model="data.name"
                  autofocus
                  size="mini"
                  :ref="'slotTreeInput'+data.parentId"
                  @blur.stop="handleAdd(node, data)"
                  @keyup.enter.native="$event.target.blur()"
                ></el-input>
              </template>
              <template v-if="node.isEdit">
                <el-input
                  v-model="data.name"
                  autofocus
                  size="mini"
                  :ref="'slotTreeInput'+data.id"
                  @blur.stop="handleInput(node, data)"
                  @keyup.enter.native="$event.target.blur()"
                ></el-input>
              </template>
              <template v-else>
                <span
                  class="el-tree-icon"
                  :class="data.children ? node.expanded ? 'el-folder-opened-icon' : 'el-folder-icon' : 'el-document-icon'"
                />
                <span>{{ data.name }}</span>
                <span v-if="node.isCurrent && !data.isHead && !data.isAdd">
                  <el-button type="text" size="mini" @click="() => appendTree(node, data)">新增</el-button>
                  <el-button type="text" size="mini" @click="() => removeTree(node, data)">删除</el-button>
                  <el-button type="text" size="mini" @click="() => updateTree(node, data)">改名</el-button>
                </span>
              </template>
            </div>
          </template>
        </el-tree>
      </div>

data中定义: 


      deptOptions: [],
      defaultProps: {
        children: "children",
        label: "name"
      },
      //是否存在顶级节点的新增
      isHeadAdd: false,
      initParam: {
        // 新增参数
        name: "",
        isAdd: true,
        children: []
      },
      initParamHead: {
        // 新增参数
        name: "",
        isAdd: true,
        isHead: true,
        children: [],
        parentId : 0, // 父id
        parentIds:0
      },
      //是否新增
      isAdd: false,

接口数据:

  methods方法

updateTree(_node, _data) {
      if (this.isAdd) {
        this.$message.error("请完成上次操作后再次点击!");
        return;
      }
      // 设置编辑状态
      if (!_node.isEdit) {
        this.$set(_node, "isEdit", true);
      }
      // 输入框聚焦
      this.$nextTick(() => {
        if (this.$refs["slotTreeInput" + _data.id]) {
          this.$refs["slotTreeInput" + _data.id].$refs.input.focus();
        }
      });
    },
    handleInput(_node, _data) {
      // 修改节点
      // 退出编辑状态
      if (_node.isEdit) {
        if (_data.name && _data.name.length > 0) {
          updateFolderTree(_data).then(res => {
            if (res.msg === "ok") {
              this.isAdd = false;
              this.$message({
                message: "修改成功",
                type: "success"
              });
              this.$set(_node, "isEdit", false);
              this.getTreeselect();
            } else {
              this.$message({
                message: "修改失败",
                type: "error"
              });
            }
          });
        } else {
          this.$message.error("名称不得为空!");
          this.isAdd = false;
          return;
        }
      }
    },
    appendTree(_node, _data) {
      if (this.isAdd) {
        this.$message.error("请新增完毕后再次点击!");
        return;
      }
      this.isAdd = true;
      // 新增节点
      // 参数修改
      let obj = JSON.parse(JSON.stringify(this.initParam)); // copy参数
      obj.parentId = _data.id; // 父id
      obj.parentIds = _data.parentIds + "," + _data.id; // 父id
      // 判断字段是否存在
      if (!_data.children) {
        this.$set(_data, "children", []);
      }
      // 新增数据
      _data.children.push(obj);
      this.$nextTick(() => {
        if (this.$refs["slotTreeInput" + _data.id]) {
          this.$refs["slotTreeInput" + _data.id].$refs.input.focus();
        }
      });
      // 展开节点
      if (!_node.expanded) {
        _node.expanded = true;
      }
    },
    handleHeadAdd(_node, _data) {
      // 修改节点
      // 退出编辑状态
      if (_data.isHead) {
        if (_data.name && _data.name.length > 0) {
          saveFolderTree(_data).then(res => {
            if (res.msg === "ok") {
              this.$message({
                message: "新增成功",
                type: "success"
              });
              this.$set(_data, "isHead", false);
              this.isAdd = false;
              this.getTreeselect();
            } else {
              this.$message({
                message: "新增失败",
                type: "error"
              });
            }
          });
        } else {
          this.isAdd = false;
          this.$message.error("名称不得为空!");
          this.getTreeselect();
        }
      }
    },
    handleAdd(_node, _data) {
      // 修改节点
      // 退出编辑状态
      if (_data.isAdd) {
        if (_data.name && _data.name.length > 0) {
          saveFolderTree(_data).then(res => {
            if (res.msg === "ok") {
              this.$message({
                message: "新增成功",
                type: "success"
              });
              this.isAdd = false;
              this.getTreeselect();
            } else {
              this.$message({
                message: "新增失败",
                type: "error"
              });
            }
          });
        } else {
          this.$message.error("名称不得为空!");
          this.isAdd = false;
          this.getTreeselect();
          // return;
        }
        this.$set(_data, "isAdd", false);
      }
    },
    handleAddTop() {
      if (!this.isAdd) {
        // 添加顶部节点
        this.isAdd = true;
        let obj = JSON.parse(JSON.stringify(this.initParamHead)); // copy参数
        if(!(this.deptOptions && this.deptOptions.length>0)){
          this.deptOptions = [];
        }
        this.deptOptions.push(obj);
        this.$nextTick(() => {
          if (this.$refs["slotTreeInputHead"]) {
            this.$refs["slotTreeInputHead"].$refs.input.focus();
          }
        });
      } else {
        this.$message.error("请新增完毕后再次点击!");
        return false;
      }
    },
    removeTree(_node, _data) {
      if (this.isAdd) {
        this.$message.error("请完成上次操作后再次点击!");
        return;
      }
      // 删除节点
      // 判断是否存在子节点
      if (_data.children && _data.children.length !== 0) {
        this.$message.error("此节点有子级,不可删除!");
        return false;
      } else {
        // 删除操作
        let DeletOprate = () => {
          this.$nextTick(() => {
            if (this.$refs.tree) {
              this.$refs.tree.remove(_data);
              this.deleteData(_data);
              // this.$message.success("删除成功!")
            }
          });
        };
        // 二次确认
        let ConfirmFun = () => {
          this.$confirm("是否删除此节点?", "提示", {
            confirmButtonText: "确认",
            cancelButtonText: "取消",
            type: "warning"
          })
            .then(() => {
              DeletOprate();
            })
            .catch(() => {});
        };
        // 判断是否新增: 新增节点直接删除,已存在的节点要二次确认
        _data[this.id] < this.NODE_ID_START ? DeletOprate() : ConfirmFun();
      }
    },
    handleDragStart(node, ev) {
    },
    handleDragEnter(draggingNode, dropNode, ev) {
    },
    handleDragLeave(draggingNode, dropNode, ev) {
    },
    handleDragOver(draggingNode, dropNode, ev) {
    },
    handleDragEnd(draggingNode, dropNode, dropType, ev) {
    },
    handleDrop(draggingNode, dropNode, dropType, ev) {
      var data = dropType != "inner" ? dropNode.parent.data : dropNode.data;
      let updateData = draggingNode.data;

      updateData.parentId = dropType != "inner" ? data.parentId : data.id;
      updateData.parentIds =
        dropType != "inner" ? data.parentIds : data.parentIds + "," + data.id;
      if (!updateData.id) {
        return;
      }
       //接口方法
      update(updateData).then(res => {
        if (res.msg === "ok") {
          this.$message({
            message: "拖拽成功",
            type: "success"
          });
          this.getTreeselect();
        } else {
          this.$message({
            message: "拖拽失败",
            type: "error"
          });
        }
      });
    },

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值