h函数是Vue 3中创建VNode的核心工具,动态Slot本质是动态调用插槽函数并传入参数返回VNode,可通过安全调用、slot映射、工厂函数等方式实现灵活控制。

在 Vue 3 的 Composition API 和底层渲染逻辑中,h 函数是创建 VNode 的核心工具。要实现动态 Slot 内容(即运行时决定插槽内容、甚至切换插槽模板),关键不是“把 slot 写死”,而是把插槽函数作为参数传入 h,并让其返回可执行的 VNode 生成逻辑。
Slot 本质是函数,不是模板字符串
Vue 中的具名或作用域插槽,在 setup 或 render 函数里都表现为一个函数:调用它,才返回 VNode 数组。所以动态控制 Slot,就是动态控制这个函数的调用时机、参数和返回值。
-
默认插槽 对应
slots.default,它可能为undefined,需判空 -
具名插槽 如
slots.header、slots.footer,也是函数 -
作用域插槽 调用时传入对象(如
{ item, index }),返回基于该数据的 VNode
用 h 渲染动态 Slot 的基本写法
在自定义组件的 render 函数中,直接调用 slots.xxx() 并传给 h 即可。若需条件渲染,就用三元或 if 判断是否调用:
render() {
return h('div', [
h('header', this.$slots.header?.()),
h('main', [
this.showList
? h('ul', this.items.map((item, i) =>
h('li', { key: i }, [this.$slots.item?.({ item, index: i })])
))
: h('p', '暂无数据')
]),
h('footer', this.$slots.footer?.())
])
}
注意:?.() 是安全调用,避免插槽未提供时报错。
动态切换插槽模板:用变量控制 slots 函数选择
你可以把多个插槽函数存在对象中,再根据状态 key 动态取用:
const slotMap = {
list: () => slots.item?.({ item: current, index: 0 }),
card: () => slots.card?.({ data: current }),
empty: () => slots.empty?.()
}
return h('div', slotMap[this.viewMode]?.() || h('span', 'loading...'))
这样就实现了「视图模式切换 → 插槽模板切换」的解耦逻辑,无需重复写 v-if 块。
封装高阶逻辑:带上下文的 Slot 工厂函数
更进一步,可以封装一个生成插槽函数的工厂,注入共享逻辑(如 loading 状态、错误 fallback):
const withLoading = (slotFn, loadingSlot) => () => {
if (isLoading.value) return loadingSlot?.() || h('span', '加载中...')
if (error.value) return h('p', error.value.message)
return slotFn()
}
return h('section', [
withLoading(() => slots.default?.(), () => slots.loading?.())()
])
这种写法把副作用(loading/error 处理)从模板层抽离到 VNode 构建层,更易测试和复用。
Slot 动态性不在于模板语法多灵活,而在于你能否把插槽当作一等函数来组合、代理、节流、缓存——h 就是你在 VNode 层自由调度这些函数的指挥棒。

















