本文介绍如何实现一个基于 vue
的递归组件的树结构!
功能
- 根据树形数据渲染出树形结构
- 点击某个节点能够收缩其子节点
- 等其他功能…
实现思路
组件在其内部是可以调用其组件自身的,使用递归的思想循环调用树列表组件自身,就可以循环往复的渲染出所有树节点,但是必须确定跳出递归的条件,避免循环引用导致无限循环而出现如下错误。
1 | Uncaught RangeError: Maximum call stack size exceeded |
根据树形数据结构,我们可以将跳出循环的条件设置为 是否存在子节点数据 ,如果有子节点数据,那继续循环,否则,跳出循环,只渲染当前节点。
代码
测试代码环境为 vue-cli-3
,组件使用单文件组件。
treeList.vue 组件
该组件为渲染树本身
1 |
|
treeLabel.vue 组件
该组件功能为,渲染当前节点标题,及其子组件数据。
1 |
|
注: 如果你使用了模块化构建系统,像包含了 webpack
或 Browserify
的 @vue/cli
,你会遇到像下面这样的错误:
1 | Failed to mount component: template or render function not defined. |
为了解释这里发生了什么,我们先把两个组件称为 A 和 B。模块系统发现它需要 A,但是首先 A 依赖 B,但是 B 又依赖 A,但是 A 又依赖 B,如此往复。这变成了一个循环,不知道如何不经过其中一个组件而完全解析出另一个组件。
为了解决这个问题,我们需要给模块系统一个点,在那里 A 反正是需要 B 的,但是我们不需要先解析 B。
所以,对于上面我们定义的两个组件,我们可以把 treeLabel
组件作为那个点,而为了告诉 模块系统 我们不需要先解析 treeList
组件,而是等到用到的时候再加载解析她。那么,我们可以这样做:
1 | const treeList = () => import('./treeList.vue') |
没错!在 webpack
这样的模块系统中,我们可以使用异步的 import()
来注册异步组件,这样只有在 treeList
组件被用到的时候才会被模块系统解析。
对于以上问题,只是会出现在 局部注册组件 时出现,如果你是以 全局注册组件 的显示定义有循环引用的两个组件时就不会出现这样的情况了。
1 | Vue.component('treeLabel', { |
使用
App.vue
1 | <template> |
至此就实现了最基本的树结构功能。