vue插槽实现原理
Vue 插槽的实现原理
Vue 插槽(Slot)的核心原理是基于编译时的模板转换和运行时的作用域处理。插槽允许父组件向子组件传递模板片段,子组件通过插槽出口(<slot>)渲染这些内容。
编译阶段处理
Vue 的模板编译器会将插槽相关语法转换为渲染函数代码:
- 父组件中通过
v-slot或默认插槽传递的内容会被编译为函数形式,保存在子组件的$slots或$scopedSlots中。 - 子组件中的
<slot>标签会被编译为对$slots或$scopedSlots的调用。
例如以下父组件模板:
<child-component>
<template v-slot:default>插槽内容</template>
</child-component>
会被编译为类似:
h('child-component', {
scopedSlots: {
default: () => '插槽内容'
}
})
运行时处理
在子组件实例化时:
- 普通插槽内容会被挂载到
vm.$slots,作用域在父组件中确定。 - 作用域插槽内容会被挂载到
vm.$scopedSlots,以函数形式接收子组件传递的数据。
子组件的 <slot> 会被转换为对 $slots 的调用:
// 编译后的渲染函数
render(h) {
return h('div', this.$slots.default)
}
作用域插槽实现
作用域插槽允许子组件向插槽传递数据,编译后会生成接收参数的函数:
<!-- 父组件 -->
<child-component>
<template v-slot:default="slotProps">{{ slotProps.text }}</template>
</child-component>
<!-- 子组件 -->
<slot :text="message"></slot>
编译后的代码类似:
// 父组件渲染函数
h('child-component', {
scopedSlots: {
default: (props) => props.text
}
})
// 子组件渲染函数
h('div', this.$scopedSlots.default({ text: this.message }))
更新机制
当插槽内容依赖响应式数据时:
- 普通插槽在父组件更新时重新生成整个 VNode。
- 作用域插槽在子组件更新时重新调用插槽函数,但函数本身只有在父组件更新时才会变化。
这种设计保证了性能优化,避免不必要的重新渲染。







