当前位置:首页 > VUE

vue 递归实现树

2026-01-08 17:09:28VUE

递归组件实现树形结构

在Vue中可以通过递归组件实现树形结构的渲染,核心思路是组件内部调用自身。以下是一个完整的实现示例:

<template>
  <div class="tree">
    <tree-node :node="treeData" @on-select="handleSelect"></tree-node>
  </div>
</template>

<script>
import TreeNode from './TreeNode.vue'

export default {
  components: { TreeNode },
  data() {
    return {
      treeData: {
        id: 1,
        label: 'Root',
        children: [
          {
            id: 2,
            label: 'Child 1',
            children: [
              { id: 3, label: 'Grandchild 1' },
              { id: 4, label: 'Grandchild 2' }
            ]
          },
          { id: 5, label: 'Child 2' }
        ]
      }
    }
  },
  methods: {
    handleSelect(node) {
      console.log('Selected node:', node)
    }
  }
}
</script>

TreeNode组件实现

<template>
  <div class="node">
    <div @click="toggle" :class="{ 'has-children': hasChildren }">
      {{ node.label }}
    </div>
    <div v-show="isOpen" v-if="hasChildren" class="children">
      <tree-node
        v-for="child in node.children"
        :key="child.id"
        :node="child"
        @on-select="$emit('on-select', $event)"
      ></tree-node>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TreeNode',
  props: {
    node: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      isOpen: false
    }
  },
  computed: {
    hasChildren() {
      return this.node.children && this.node.children.length
    }
  },
  methods: {
    toggle() {
      if (this.hasChildren) {
        this.isOpen = !this.isOpen
      }
      this.$emit('on-select', this.node)
    }
  }
}
</script>

<style>
.node {
  margin-left: 20px;
  cursor: pointer;
}
.has-children {
  font-weight: bold;
}
.children {
  margin-left: 15px;
}
</style>

关键实现要点

递归组件的核心是在组件内部通过name属性注册自身,然后在模板中直接使用。必须设置name属性才能实现递归调用。

数据结构通常采用嵌套的children形式,每个节点包含:

vue 递归实现树

  • id: 唯一标识
  • label: 显示文本
  • children: 子节点数组(可选)

通过v-show控制子节点的展开/折叠状态,计算属性hasChildren判断当前节点是否有子节点。

性能优化建议

对于大型树结构,可以采用虚拟滚动优化:

vue 递归实现树

  1. 计算可见区域内的节点
  2. 只渲染可见部分节点
  3. 滚动时动态更新渲染节点
// 虚拟滚动示例
const visibleNodes = computed(() => {
  return allNodes.value.slice(
    startIndex.value,
    Math.min(startIndex.value + visibleCount.value, allNodes.value.length)
  )
})

动态加载实现

当树节点数据量很大时,可以按需加载子节点:

methods: {
  async loadChildren(node) {
    if (!node.childrenLoaded && !node.children) {
      const res = await api.getChildren(node.id)
      this.$set(node, 'children', res.data)
      this.$set(node, 'childrenLoaded', true)
    }
    this.isOpen = !this.isOpen
  }
}

注意事项

递归组件需要合理控制递归深度,过深的嵌套可能导致堆栈溢出。建议对树形数据做扁平化处理时设置最大深度限制。

组件样式需要注意层级缩进,通过margin-left实现视觉上的树形层次感。交互方面建议添加展开/折叠动画提升用户体验。

标签: 递归vue
分享给朋友:

相关文章

vue实现表白

vue实现表白

Vue 实现表白页面 使用 Vue 可以快速创建一个动态、交互式的表白页面。以下是一个简单的实现方案: 基础结构 创建一个 Vue 项目或单文件组件,包含以下核心部分: <template&…

vue实现必填

vue实现必填

Vue 实现表单必填验证的方法 在Vue中实现表单必填验证可以通过多种方式完成,以下是几种常见的方法: 使用HTML5原生属性 最简单的必填验证可以通过HTML5的required属性实现: &l…

vue实现dialog

vue实现dialog

Vue 实现 Dialog 的方法 使用 Vue 原生组件实现 Vue 可以通过组件化的方式实现 Dialog,以下是一个简单的实现示例: <template> <div>…

vue实现组件跟随

vue实现组件跟随

实现组件跟随的常见方法 使用CSS定位 通过CSS的position: fixed或position: absolute属性实现组件跟随。需要结合JavaScript计算目标元素的位置。 &…

vue实现转盘抽奖

vue实现转盘抽奖

Vue 实现转盘抽奖 基本思路 转盘抽奖的核心是通过 CSS 动画实现旋转效果,Vue 负责控制旋转逻辑和数据绑定。关键点包括转盘扇形区域的绘制、旋转动画的触发与停止、中奖结果的判定。 实现步骤 H…

vue 实现异步加载

vue 实现异步加载

Vue 实现异步加载的方法 使用动态 import 实现组件懒加载 在 Vue 中可以通过动态 import() 语法实现组件的异步加载,这会使得组件在需要时才被加载,减少初始加载时间。 const…