递归组件中slots不会自动穿透,必须显式透传:在每一层用包裹并重传,确保子节点能访问各自作用域数据。

Slots 是 Vue 中内容分发的核心机制
在递归组件中,slots 不会自动穿透到子级递归调用处。默认情况下,父组件传入的插槽内容只作用于当前组件实例,不会随着 <component :is="..."></component> 或递归调用(如 <treenode :nodes="childNodes"></treenode>)向下传递。要实现嵌套结构中的内容分发,必须显式地在每一层递归组件中 接收并重新渲染 slot。
递归组件中正确使用 slots 的关键写法
以树形节点组件 TreeNode.vue 为例,需同时满足:支持递归渲染 + 支持自定义节点内容(如图标、操作按钮等):
- 在模板中用
<slot></slot>渲染当前节点的自定义内容(即“节点本体”) - 对子节点列表,用
v-for渲染子TreeNode组件,并确保 把当前作用域的 slot 显式透传下去 - 使用
v-bind="$attrs"和v-on="$listeners"(Vue 2)或v-bind="$attrs"(Vue 3 默认继承)保持属性/事件透传,但 slot 必须手动处理
Vue 3 中推荐的递归 slot 写法(简洁可靠)
利用 <slot></slot> 默认行为 + defineSlots 类型提示(可选),并在子组件调用时用 <template></template> 显式转发:
<!-- TreeNode.vue -->
<template><div class="tree-node">
<!-- 当前节点内容由父级传入的 default slot 渲染 -->
<slot :node="node"></slot><pre class="brush:php;toolbar:false;"><!-- 递归渲染子节点,且把当前 slot 向下透传 -->
<treenode v-for="child in node.children" :key="child.id" :node="child"><!-- 关键:把上层 slot 再次作为 default 插槽传给子组件 --><template><slot name="default" v-bind="childSlotProps"></slot></template></treenode>











