You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3:用渲染函数渲染带插槽嵌套组件,为何代码不生效?

失效原因与踩坑点分析

1. 插槽传递未做正确映射

Vue3的render函数中,直接将父组件的$slots传给动态渲染的AppItem1/AppItem2是无效的。作为中间组件,AppItem需要手动将自身接收的所有插槽(包括默认插槽和具名插槽)一一透传给目标组件,且每个插槽必须包装成返回VNode的函数,不能直接传递VNode数组。

错误示例:

// 错误:未处理插槽透传
render() {
  const Comp = `AppItem${this.level}`
  return h(Comp)
}

正确写法:

render() {
  // 确保使用组件对象而非字符串
  const TargetComp = this[`AppItem${this.level}`]
  return h(TargetComp, {}, {
    default: () => this.$slots.default?.(),
    // 按实际需求透传所有具名插槽
    header: () => this.$slots.header?.(),
    footer: () => this.$slots.footer?.()
  })
}

2. 动态组件引用方式错误

你大概率直接用字符串拼接的组件名调用h函数了(比如h('AppItem' + this.level))——Vue3的h函数需要传入组件对象而非字符串。要么在AppItem的components选项中注册AppItem1/AppItem2,要么直接导入组件后使用。

3. 嵌套组件的插槽透传断层

AppItem1/AppItem2内部嵌套了AppBlock,但如果AppItem1的模板没有将自身接收的插槽透传给AppBlock,即使AppItem传对了插槽,最终也无法在AppBlock中显示。比如AppItem1的模板需要这样写:

<template>
  <AppBlock>
    <template #default>
      <slot /> <!-- 透传默认插槽给AppBlock -->
    </template>
    <template #header>
      <slot name="header" /> <!-- 对应透传具名插槽 -->
    </template>
  </AppBlock>
</template>

4. 对Vue3 render函数插槽API理解偏差

很多人会错误地将插槽写成default: this.$slots.default,但Vue3要求插槽对象的每个值必须是返回VNode的函数,否则插槽无法响应数据更新,渲染逻辑也会出错。必须用() => this.$slots.xxx?.()的形式包裹。

5. level属性未做响应式处理

如果level不是响应式的(比如只是普通变量,不是props也不是用ref/reactive声明的),当level变化时render函数不会重新执行,组件自然不会切换为对应的AppItem1/AppItem2。要确保level是AppItem的props(props天生响应式),或是用ref声明的变量。


内容的提问来源于stack exchange,提问作者Paulo R.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:10:19