Vue单文件组件可用render函数替代template实现动态渲染,需移除template并用setup返回render,配合h函数生成VNode,支持响应式数据、插槽、动态标签及组件。

Vue 单文件组件(.vue)默认使用模板语法(<template>),但你完全可以在其中用 render 函数替代模板,实现更灵活、动态的渲染逻辑——比如根据运行时条件生成不同结构、封装高阶组件、或在编译阶段无法确定节点形态的场景。
在 SFC 中启用 render 函数
单文件组件中不能同时存在 <template> 和 render 选项(Vue 会优先使用 template,忽略 render)。要使用 render,必须显式移除 <template> 标签,并在 setup() 或 export default 配置中定义 render 函数。
- Vue 3 推荐在
setup()中返回render(需配合h函数) -
render必须返回一个 VNode(即h()的调用结果) - 响应式数据需通过
ref/reactive声明,并在render中直接读取(触发依赖收集)
基础写法:setup + h + render
以下是一个带状态和条件逻辑的 render 示例:
<script setup>
import { ref, h } from 'vue'
const count = ref(0)
const showTitle = ref(true)
// render 函数必须命名为 `render`,且是 setup 的返回值
const render = () => {
return h('div', { class: 'wrapper' }, [
showTitle.value && h('h1', '动态标题'),
h('p', `当前计数:${count.value}`),
h('button', {
onClick: () => count.value++
}, '加一'),
h('button', {
onClick: () => showTitle.value = !showTitle.value
}, showTitle.value ? '隐藏标题' : '显示标题')
])
}
</script>
<style scoped>
.wrapper { padding: 16px; }
</style>
处理插槽与 Props(保持组件复用性)
render 函数中可通过 defineProps 获取 props,用 slots 访问具名/默认插槽:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
立即学习“前端免费学习笔记(深入)”;
- 使用
defineProps({ ... })声明 props 类型(TS 更友好) - 通过
defineSlots()(Vue 3.3+)或useSlots()获取插槽函数 - 插槽内容需手动调用(如
slots.default?.()),支持传参
<script setup>
import { defineProps, useSlots, h } from 'vue'
const props = defineProps({
title: String,
disabled: Boolean
})
const slots = useSlots()
const render = () => {
return h('div', { class: 'card' }, [
props.title && h('header', props.title),
h('main', slots.default?.()),
props.disabled || slots.footer?.()
])
}
</script>
进阶:用 render 封装动态标签或组件
当需要根据 prop 渲染不同 HTML 标签或组件时,render 比 v-if/v-else 更简洁:
- 动态 tag:用变量作为
h()第一个参数,如h(tag, ...) - 动态组件:传入组件对象(可从 import 或 resolveComponent 得到)
- 避免模板中大量嵌套 v-if,逻辑更集中、易测试
例如:h(props.as || 'div', ...) 实现语义化标签切换;h(resolveDynamicComponent(props.component), ...) 加载异步组件。

















