返回 导航

其他

hangge.com

Vue.js - 使用Element-UI的tree组件实现可编辑树教程(双击编辑、新增、删除节点)

作者:hangge | 2024-08-23 08:27
    树形图是我们项目经常用到的一个组件。本文将介绍如何利用 Element-UItree 组件实现一个可编辑的树形结构,通过简单的操作实现节点的新增、删除和编辑功能。

1,效果图

(1)点击“新增”按钮后,在选中节点下会新增一个输入框,输入内容回车后(或者失去焦点时)插入新的子节点。

(2)选中一个节点后点击“删除”按钮可以将选中节点删除:

(3)双击某个节点文字,该节点会变成一个文本输入框,输入新的内容回车后(或者失去焦点时)则会更新此节点名称。

2,样例代码

<template>
  <div id="container">
    <!-- 新增按钮 -->
    <el-button type="primary" size="small" icon="el-icon-plus" 
      @click="addNode" :disabled="!this.selectedNode">新增</el-button>
    <!-- 删除按钮 -->
    <el-button type="danger" size="small" icon="el-icon-delete" 
      @click="delNode" :disabled="!this.selectedNode">删除</el-button>
    <!-- 树组件 -->
    <el-tree class="my-tree" :data="treeData" :props="defaultProps"
      show-checkbox :default-expand-all="true"
      highlight-current :expand-on-click-node="false" 
      @node-click="nodeClick" :render-content="renderContent">
    </el-tree>
  </div>
</template>

<script>
export default {
  name: 'MyTree',
  data() {
    return {
      treeData: [
        {
          id: 1,
          name: "电子产品",
          children: [
            {
              id: 2,
              name: "电脑",
              children: [
                {
                  id: 3, name: "苹果笔记本", children: []
                },
                {
                  id: 4, name: "戴尔笔记本", children: []
                }
              ]
            },
            {
              id: 5,
              name: "手机",
              children: [
                {
                  id: 6, name: "iPhone", children: []
                },
                {
                  id: 7, name: "三星Galaxy", children: []
                }
              ]
            }
          ]
        },
        {
          id: 8,
          name: "家具",
          children: [
            {
              id: 9,
              name: "椅子",
              children: [
                {
                  id: 10, name: "网易严选办公椅", children: []
                }
              ]
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      selectedNode: null, // 当前选中的节点
      editingNode: null, // 当前正在编辑的节点
    }
  },
  methods: {
    // 渲染树节点显示的内容
    renderContent(h, { node, data }) {
      if (this.editingNode === data) {
        return (
          <el-input
            vModel={data.name}
            size="mini"
            onInput={(value) => this.handleInput(value, data)}
            onChange={() => this.handleBlur(data)}
            nativeOnDblclick={(event) => event.stopPropagation()}
          />
        );
      } else {
        return (
          <span onDblclick={() => this.handleNodeDblClick(data)}>
            {data.name}
          </span>
        );
      }
    },
    // 树节点双击响应
    handleNodeDblClick(data) {
      // 至于区域层级双击有效
      this.editingNode = data;
      this.$nextTick(() => {
        const input = this.$el.querySelector(`.tree .el-input input`);
        if (input) {
          input.focus();
        }
      });
    },
    // 树节点编辑状态下输入响应
    handleInput(value, data) {
      data.name = value;
    },
    // 树节点编辑状态下失去焦点响应
    handleBlur(data) {
      this.editingNode = null;
      // 如果id不为空,则更新逻辑分组,否则新增逻辑分组
      if (data.id) {
        // this.doUpdate(data);
        this.$notify({
          title: '修改成功',
          type: 'success'
        });
      } else {
        // this.doAdd(data);
        this.$notify({
          title: '新增成功',
          type: 'success'
        });
      }
    },
    // 树节点单击响应
    nodeClick(data, node) {
      this.selectedNode = data;
      if(this.selectedNode != this.editingNode) {
        this.editingNode = null;
      }
    },
    // 新增节点
    addNode() {
      let item = {
        "children": [],
        "name": "",
        "id": ""
      }
      this.editingNode = item
      this.selectedNode.children.push(item);
      this.$nextTick(() => {
        const input = this.$el.querySelector(`.tree .el-input input`);
        if (input) {
          input.focus();
        }
      });
    },
    // 删除节点
    delNode() {
      for(let node of this.treeData) {
        this.recursionDelNode(node)
      }
      // 弹出提示消息
      this.$notify({
        title: '删除成功',
        type: 'success'
      });
    },
    // 递归删除节点
    recursionDelNode(node) {
      if (node.children) {
        node.children = node.children.filter(item => item !== this.selectedNode);
        for(let child of node.children) {
          this.recursionDelNode(child);
        }
      }
    }
  }
}
</script>
<style scoop>
  #container {
    padding: 20px;
  }

  .my-tree {
    margin-top: 20px;
  }
</style>
评论

全部评论(0)

回到顶部