当前位置:首页 > VUE

vue实现树穿梭

2026-01-11 23:34:49VUE

Vue 实现树穿梭功能

树穿梭功能通常用于在两个树形结构之间移动节点,常见于权限管理、数据分类等场景。以下是基于 Vue 的实现方法:

使用 Element UI 的 Tree 组件

Element UI 提供了成熟的 Tree 和 Transfer 组件,可以组合实现树穿梭功能。

安装 Element UI:

npm install element-ui

示例代码:

<template>
  <div>
    <el-transfer
      v-model="selectedNodes"
      :data="treeData"
      :props="treeProps"
      :left-default-checked="leftChecked"
      :right-default-checked="rightChecked"
      filterable
      :titles="['源树', '目标树']"
    >
      <el-tree
        slot="left"
        ref="leftTree"
        :data="leftTreeData"
        :props="treeProps"
        show-checkbox
        node-key="id"
        @check-change="handleLeftCheckChange"
      ></el-tree>
      <el-tree
        slot="right"
        ref="rightTree"
        :data="rightTreeData"
        :props="treeProps"
        show-checkbox
        node-key="id"
        @check-change="handleRightCheckChange"
      ></el-tree>
    </el-transfer>
  </div>
</template>

<script>
export default {
  data() {
    return {
      leftTreeData: [
        { id: 1, label: '一级 1', children: [{ id: 4, label: '二级 1-1' }] },
        { id: 2, label: '一级 2', children: [{ id: 5, label: '二级 2-1' }] },
        { id: 3, label: '一级 3', children: [{ id: 6, label: '二级 3-1' }] }
      ],
      rightTreeData: [],
      selectedNodes: [],
      treeProps: {
        label: 'label',
        children: 'children'
      },
      leftChecked: [],
      rightChecked: []
    }
  },
  methods: {
    handleLeftCheckChange(node, checked) {
      if (checked) {
        this.leftChecked = [...this.leftChecked, node.id]
      } else {
        this.leftChecked = this.leftChecked.filter(id => id !== node.id)
      }
    },
    handleRightCheckChange(node, checked) {
      if (checked) {
        this.rightChecked = [...this.rightChecked, node.id]
      } else {
        this.rightChecked = this.rightChecked.filter(id => id !== node.id)
      }
    }
  },
  computed: {
    treeData() {
      return [...this.leftTreeData, ...this.rightTreeData]
    }
  }
}
</script>

自定义实现树穿梭

如果需要更自定义的功能,可以完全自己实现:

<template>
  <div class="tree-transfer">
    <div class="tree-container">
      <h3>源树</h3>
      <tree
        :data="sourceTree"
        :props="treeProps"
        show-checkbox
        node-key="id"
        ref="sourceTree"
        @check-change="handleSourceCheckChange"
      ></tree>
    </div>
    <div class="transfer-buttons">
      <button @click="moveToTarget">→</button>
      <button @click="moveToSource">←</button>
    </div>
    <div class="tree-container">
      <h3>目标树</h3>
      <tree
        :data="targetTree"
        :props="treeProps"
        show-checkbox
        node-key="id"
        ref="targetTree"
        @check-change="handleTargetCheckChange"
      ></tree>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sourceTree: [
        { id: 1, label: '节点1', children: [{ id: 2, label: '子节点1' }] },
        { id: 3, label: '节点2' }
      ],
      targetTree: [],
      treeProps: {
        label: 'label',
        children: 'children'
      },
      checkedSourceNodes: [],
      checkedTargetNodes: []
    }
  },
  methods: {
    handleSourceCheckChange(node, checked) {
      if (checked) {
        this.checkedSourceNodes.push(node.id)
      } else {
        this.checkedSourceNodes = this.checkedSourceNodes.filter(id => id !== node.id)
      }
    },
    handleTargetCheckChange(node, checked) {
      if (checked) {
        this.checkedTargetNodes.push(node.id)
      } else {
        this.checkedTargetNodes = this.checkedTargetNodes.filter(id => id !== node.id)
      }
    },
    moveToTarget() {
      const nodesToMove = this.$refs.sourceTree.getCheckedNodes()
      this.targetTree = [...this.targetTree, ...nodesToMove]
      this.sourceTree = this.removeNodes(this.sourceTree, this.checkedSourceNodes)
      this.checkedSourceNodes = []
    },
    moveToSource() {
      const nodesToMove = this.$refs.targetTree.getCheckedNodes()
      this.sourceTree = [...this.sourceTree, ...nodesToMove]
      this.targetTree = this.removeNodes(this.targetTree, this.checkedTargetNodes)
      this.checkedTargetNodes = []
    },
    removeNodes(tree, ids) {
      return tree.filter(node => {
        if (ids.includes(node.id)) return false
        if (node.children) {
          node.children = this.removeNodes(node.children, ids)
        }
        return true
      })
    }
  }
}
</script>

<style>
.tree-transfer {
  display: flex;
  justify-content: space-between;
}
.tree-container {
  width: 45%;
}
.transfer-buttons {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
</style>

关键实现要点

  1. 双向数据绑定:维护源树和目标树两个数据源,通过操作这两个数组实现节点移动。

  2. 节点选择:利用 Tree 组件的复选框功能,记录选中的节点。

  3. 节点移动:将选中节点从源树移到目标树,或反向移动。

  4. 树形结构处理:递归处理子节点,确保移动时保持树形结构完整。

  5. 性能优化:对于大型树结构,考虑使用虚拟滚动或懒加载技术。

注意事项

  1. 节点标识:确保每个节点有唯一标识符(如id),便于操作和查找。

  2. 状态同步:移动节点后及时清空已选节点列表。

  3. 深度复制:移动节点时进行深拷贝,避免引用问题。

  4. 自定义样式:根据需求调整穿梭框和按钮的样式布局。

以上两种方法都可以实现树穿梭功能,Element UI 方案更快捷,自定义方案更灵活。可以根据项目需求选择适合的实现方式。

vue实现树穿梭

标签: vue
分享给朋友:

相关文章

vue实现文档导入

vue实现文档导入

Vue 实现文档导入的方法 在 Vue 中实现文档导入功能通常涉及文件上传、解析和处理。以下是几种常见的方法: 使用原生文件输入和 FileReader 通过 HTML 的原生 <input…

在线脑图 vue 实现

在线脑图 vue 实现

在线脑图 Vue 实现方案 使用开源库实现 推荐使用 mind-elixir 或 jsmind 这类开源库,它们专为脑图设计且支持 Vue 集成。 安装依赖: npm install mi…

vue实现表格多行修改

vue实现表格多行修改

实现多行编辑表格 在Vue中实现表格的多行编辑功能,可以通过以下方法完成。这里以Element UI的表格组件为例,但思路适用于其他UI库或原生实现。 数据准备 定义表格数据和编辑状态管理变量:…

vue实现按卡片轮播

vue实现按卡片轮播

实现卡片轮播的基本思路 在Vue中实现卡片轮播可以通过结合v-for指令和动态样式绑定完成。核心是维护一个当前显示卡片的索引,通过CSS过渡效果实现平滑切换。 基础实现步骤 模板部分 使用v-for…

vue使用vr实现标注

vue使用vr实现标注

Vue 中使用 VR 实现标注的方法 在 Vue 项目中结合 VR 技术实现标注功能,可以通过 WebXR 和 Three.js 等库实现。以下为具体实现方法: 安装依赖 确保项目中已安装 Thr…

vue实现走势图

vue实现走势图

Vue 实现走势图的方法 使用 ECharts 库 ECharts 是一个强大的数据可视化库,支持多种图表类型,包括走势图(折线图)。在 Vue 项目中可以通过 vue-echarts 封装库或直接使…