递归组件需显式声明name属性,模板中调用自身并设双重终止条件(防null/undefined及空数组),数据应预处理为规范树结构,key须用唯一id,状态宜集中管理,超深树需优化渲染。

核心就一条:让组件自己渲染自己,但必须设好“停下来的开关”。
递归调用是基础,name 属性不能少
在 Vue 或小程序中写递归组件,第一步是给组件显式声明 name。比如 Vue 里写 name: 'TreeNode',小程序里注册组件时也要确保组件名可被模板识别。没有这个 name,模板里写 <treenode></treenode> 就会报错——它不认识自己是谁。
模板里直接调用自身,结构干净利落:
- 渲染当前节点内容(如名称、图标、展开箭头)
- 检查是否有子节点:
v-if="node.children && node.children.length" - 有,就再塞一个
<treenode></treenode>进去,把child当作新node传下去
终止条件要写牢,别让递归“刹不住车”
最常见翻车点:只判断 children 存在,却忽略它是 null、undefined 还是空数组。空数组 [] 是合法值,说明“有子节点结构,但暂时为空”,不该终止;而 null 或 undefined 才代表真没下一层。
稳妥写法是两层防护:
- 入口先保底:
if (!node || !node.id) return(防数据残缺) - 递归分支加判断:
Array.isArray(node.children) && node.children.length > 0
数据结构得规整,扁平转嵌套有更稳解法
后端常返回扁平数组(带 id 和 parent_id),直接丢给递归组件会出问题。推荐用一次遍历 + Map 构建树,不靠递归函数,避免栈溢出风险:
- 新建
Map缓存所有节点,key 是id - 遇到无
parent_id的节点,推入roots数组 - 遇到有
parent_id的节点,先确保父节点已在 Map 中(不存在就创建空 children),再把当前节点塞进父节点的children数组
这样生成的树,层级任意深,结构干净,递归组件拿来即用。
渲染时别踩坑:key、状态、性能都得管
React 或 Vue 中递归渲染,容易因 key 不稳定导致重绘错乱。每个节点必须用唯一且不变的 id 作 key,别用索引或临时生成 ID。
展开/收起状态建议提一层管理(比如用 Map 记录 id → isOpen),而不是每层组件自己维护,否则父子联动会失序。
如果树特别深(比如上千层),纯递归渲染可能卡顿。这时可考虑懒加载 + 虚拟滚动,或者改用迭代式渲染逻辑,用栈或队列代替调用栈。










