vue中怎么使用elementui实现树组件tree右键增删改功能

发布时间:2022-08-11 13:58:03 作者:iii
来源:亿速云 阅读:482

Vue中怎么使用ElementUI实现树组件Tree右键增删改功能

目录

  1. 引言
  2. ElementUI Tree组件简介
  3. 项目环境搭建
  4. 基本Tree组件的使用
  5. 实现右键菜单功能
  6. 实现节点的增删改功能
  7. 完整代码示例
  8. 总结

引言

在现代Web开发中,树形结构(Tree)是一种常见的数据展示方式,尤其是在需要展示层级关系的数据时,树形结构能够非常直观地呈现数据之间的关系。ElementUI作为一款基于Vue.js的UI组件库,提供了丰富的组件来帮助开发者快速构建用户界面。其中,el-tree组件是一个非常强大的树形结构组件,支持多种功能,如节点展开/折叠、节点选择、节点拖拽等。

然而,ElementUI的el-tree组件默认并不支持右键菜单功能,这在某些场景下可能会限制其使用。本文将详细介绍如何在Vue项目中使用ElementUI的el-tree组件,并通过自定义右键菜单实现节点的增删改功能。

ElementUI Tree组件简介

el-tree是ElementUI提供的一个树形结构组件,支持以下功能:

el-tree组件的基本用法如下:

<template>
  <el-tree :data="treeData" :props="defaultProps"></el-tree>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          label: '一级 1',
          children: [
            {
              label: '二级 1-1',
              children: [
                {
                  label: '三级 1-1-1'
                }
              ]
            }
          ]
        },
        {
          label: '一级 2',
          children: [
            {
              label: '二级 2-1',
              children: [
                {
                  label: '三级 2-1-1'
                }
              ]
            },
            {
              label: '二级 2-2',
              children: [
                {
                  label: '三级 2-2-1'
                }
              ]
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    };
  }
};
</script>

在这个例子中,我们定义了一个简单的树形结构,并通过el-tree组件将其渲染出来。

项目环境搭建

在开始实现右键菜单功能之前,我们需要先搭建一个Vue项目,并引入ElementUI库。

1. 创建Vue项目

首先,使用Vue CLI创建一个新的Vue项目:

vue create vue-tree-demo

在创建项目时,选择默认配置即可。

2. 安装ElementUI

进入项目目录,并安装ElementUI:

cd vue-tree-demo
npm install element-ui --save

3. 引入ElementUI

src/main.js中引入ElementUI:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  render: h => h(App),
}).$mount('#app');

4. 创建Tree组件

src/components目录下创建一个新的组件TreeDemo.vue,并在App.vue中引入该组件。

src/components/TreeDemo.vue

<template>
  <div class="tree-demo">
    <el-tree :data="treeData" :props="defaultProps"></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          label: '一级 1',
          children: [
            {
              label: '二级 1-1',
              children: [
                {
                  label: '三级 1-1-1'
                }
              ]
            }
          ]
        },
        {
          label: '一级 2',
          children: [
            {
              label: '二级 2-1',
              children: [
                {
                  label: '三级 2-1-1'
                }
              ]
            },
            {
              label: '二级 2-2',
              children: [
                {
                  label: '三级 2-2-1'
                }
              ]
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    };
  }
};
</script>

<style scoped>
.tree-demo {
  padding: 20px;
}
</style>

src/App.vue

<template>
  <div id="app">
    <TreeDemo />
  </div>
</template>

<script>
import TreeDemo from './components/TreeDemo.vue';

export default {
  components: {
    TreeDemo
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

5. 运行项目

在项目根目录下运行以下命令启动项目:

npm run serve

打开浏览器,访问http://localhost:8080,你应该能够看到一个简单的树形结构。

基本Tree组件的使用

在上一节中,我们已经创建了一个简单的树形结构。接下来,我们将进一步探索el-tree组件的其他功能。

1. 节点选择

el-tree组件支持节点的单选和多选。我们可以通过show-checkbox属性来启用多选功能。

<template>
  <div class="tree-demo">
    <el-tree :data="treeData" :props="defaultProps" show-checkbox></el-tree>
  </div>
</template>

2. 节点展开/折叠

el-tree组件默认支持节点的展开和折叠。我们可以通过default-expand-all属性来设置所有节点默认展开。

<template>
  <div class="tree-demo">
    <el-tree :data="treeData" :props="defaultProps" default-expand-all></el-tree>
  </div>
</template>

3. 节点拖拽

el-tree组件支持节点的拖拽功能。我们可以通过draggable属性来启用拖拽功能。

<template>
  <div class="tree-demo">
    <el-tree :data="treeData" :props="defaultProps" draggable></el-tree>
  </div>
</template>

4. 自定义节点内容

el-tree组件允许我们自定义节点的内容。我们可以通过scoped slot来实现自定义节点内容。

<template>
  <div class="tree-demo">
    <el-tree :data="treeData" :props="defaultProps">
      <span slot-scope="{ node, data }" class="custom-tree-node">
        <span>{{ node.label }}</span>
        <span>
          <el-button type="text" size="mini" @click="append(data)">添加</el-button>
          <el-button type="text" size="mini" @click="remove(node, data)">删除</el-button>
        </span>
      </span>
    </el-tree>
  </div>
</template>

<script>
export default {
  methods: {
    append(data) {
      const newChild = { label: '新节点', children: [] };
      if (!data.children) {
        this.$set(data, 'children', []);
      }
      data.children.push(newChild);
    },
    remove(node, data) {
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const index = children.findIndex(d => d.id === data.id);
      children.splice(index, 1);
    }
  }
};
</script>

<style scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>

在这个例子中,我们为每个节点添加了两个按钮:“添加”和“删除”。点击“添加”按钮可以在当前节点下添加一个新的子节点,点击“删除”按钮可以删除当前节点。

实现右键菜单功能

虽然el-tree组件提供了丰富的功能,但它默认并不支持右键菜单。为了实现右键菜单功能,我们需要借助Vue的自定义指令和ElementUI的el-menu组件。

1. 创建右键菜单组件

首先,我们创建一个新的组件ContextMenu.vue,用于显示右键菜单。

src/components/ContextMenu.vue

<template>
  <div v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="context-menu">
    <el-menu @select="handleSelect">
      <el-menu-item index="add">添加</el-menu-item>
      <el-menu-item index="edit">编辑</el-menu-item>
      <el-menu-item index="delete">删除</el-menu-item>
    </el-menu>
  </div>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      left: 0,
      top: 0,
      selectedNode: null
    };
  },
  methods: {
    showMenu(event, node) {
      this.visible = true;
      this.left = event.clientX;
      this.top = event.clientY;
      this.selectedNode = node;
    },
    hideMenu() {
      this.visible = false;
    },
    handleSelect(index) {
      this.$emit('select', index, this.selectedNode);
      this.hideMenu();
    }
  }
};
</script>

<style scoped>
.context-menu {
  position: fixed;
  z-index: 1000;
  background-color: #fff;
  border: 1px solid #ebeef5;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>

在这个组件中,我们定义了一个右键菜单,包含“添加”、“编辑”和“删除”三个选项。菜单的显示位置通过lefttop属性来控制。

2. 在Tree组件中使用右键菜单

接下来,我们在TreeDemo.vue中使用ContextMenu组件,并为其绑定事件。

src/components/TreeDemo.vue

<template>
  <div class="tree-demo">
    <el-tree
      :data="treeData"
      :props="defaultProps"
      @node-contextmenu="handleNodeContextMenu"
    ></el-tree>
    <ContextMenu ref="contextMenu" @select="handleMenuSelect"></ContextMenu>
  </div>
</template>

<script>
import ContextMenu from './ContextMenu.vue';

export default {
  components: {
    ContextMenu
  },
  data() {
    return {
      treeData: [
        {
          label: '一级 1',
          children: [
            {
              label: '二级 1-1',
              children: [
                {
                  label: '三级 1-1-1'
                }
              ]
            }
          ]
        },
        {
          label: '一级 2',
          children: [
            {
              label: '二级 2-1',
              children: [
                {
                  label: '三级 2-1-1'
                }
              ]
            },
            {
              label: '二级 2-2',
              children: [
                {
                  label: '三级 2-2-1'
                }
              ]
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    };
  },
  methods: {
    handleNodeContextMenu(event, data, node, component) {
      event.preventDefault();
      this.$refs.contextMenu.showMenu(event, node);
    },
    handleMenuSelect(index, node) {
      switch (index) {
        case 'add':
          this.append(node);
          break;
        case 'edit':
          this.edit(node);
          break;
        case 'delete':
          this.remove(node);
          break;
      }
    },
    append(node) {
      const newChild = { label: '新节点', children: [] };
      if (!node.data.children) {
        this.$set(node.data, 'children', []);
      }
      node.data.children.push(newChild);
    },
    edit(node) {
      this.$prompt('请输入节点名称', '编辑节点', {
        inputValue: node.data.label
      }).then(({ value }) => {
        node.data.label = value;
      });
    },
    remove(node) {
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const index = children.findIndex(d => d.id === node.data.id);
      children.splice(index, 1);
    }
  }
};
</script>

<style scoped>
.tree-demo {
  padding: 20px;
}
</style>

在这个例子中,我们通过@node-contextmenu事件监听树节点的右键点击事件,并在事件处理函数中调用ContextMenu组件的showMenu方法来显示右键菜单。当用户选择菜单项时,handleMenuSelect方法会根据选择的菜单项执行相应的操作。

实现节点的增删改功能

在上一节中,我们已经实现了右键菜单的基本功能。接下来,我们将进一步完善节点的增删改功能。

1. 添加节点

append方法中,我们已经在当前节点下添加了一个新的子节点。为了确保新节点的唯一性,我们可以为每个节点生成一个唯一的ID。

append(node) {
  const newChild = { id: this.generateId(), label: '新节点', children: [] };
  if (!node.data.children) {
    this.$set(node.data, 'children', []);
  }
  node.data.children.push(newChild);
},
generateId() {
  return '_' + Math.random().toString(36).substr(2, 9);
}

2. 编辑节点

edit方法中,我们使用el-prompt组件来弹出一个输入框,允许用户编辑节点的名称。

edit(node) {
  this.$prompt('请输入节点名称', '编辑节点', {
    inputValue: node.data.label
  }).then(({ value }) => {
    node.data.label = value;
  });
}

3. 删除节点

remove方法中,我们已经实现了删除节点的功能。为了确保删除操作的安全性,我们可以在删除前弹出一个确认对话框。

remove(node) {
  this.$confirm('确定要删除该节点吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    const parent = node.parent;
    const children = parent.data.children || parent.data;
    const index = children.findIndex(d => d.id === node.data.id);
    children.splice(index, 1);
  });
}

完整代码示例

以下是完整的TreeDemo.vueContextMenu.vue代码示例。

src/components/TreeDemo.vue

”`vue