Vue 插槽 (Slots) 原理

1. 面试题

Q: 默认插槽、具名插槽、作用域插槽有什么区别?Vue 3 对插槽做了什么优化?

2. 三种插槽

(1) 默认插槽 (Default)

父组件的内容直接分发到子组件的 <slot /> 位置。

(2) 具名插槽 (Named)

当子组件有多个分发点(Header, Main, Footer)时使用。

  • 用法<template #header>...</template> (v-slot 缩写为 #)。

(3) 作用域插槽 (Scoped)

核心作用数据反向传递。让父组件在渲染插槽内容时,能访问到子组件的数据。

  • 子组件<slot :item="item" />
  • 父组件<template #default="{ item }">{{ item.name }}</template>

3. 实现原理与优化

(1) Vue 2 实现

  • 普通插槽:在父组件编译阶段直接生成 VNodes,传给子组件。缺点:父组件更新,子组件也被迫更新。
  • 作用域插槽:编译成函数,子组件渲染时调用。

(2) Vue 3 优化 (All Slots are Functions)

  • 统一:Vue 3 将所有插槽(包括默认和具名)都编译为函数
  • 延迟渲染:只有当子组件渲染该 slot 时,才执行函数生成 VNodes。
  • 收益
    • 父组件更新,只重新渲染父组件。
    • 子组件插槽内容变化,只触发子组件更新。
    • 实现了父子更新隔离,性能大幅提升。