Vue 插槽 (slot) 完全指南

1. 什么是 slot

slot 插槽,可以理解为 slot 在组件模板中占好了位置,当使用该组件标签时,组件标签里面的内容就会自动填坑(替换组件模板中 slot 位置),作为承载分发内容的出口。

2. 使用场景

通过插槽可以让用户拓展组件,从而更好地复用组件和对其做定制化处理。

如果父组件在使用到一个复用组件时,获取这个组件在不同地方有少量更改,重写组件是不明智的。通过 slot 插槽向组件内部指定位置传递内容,可以完成这个复用组件在不同场景的应用。

常见的应用场景:布局组件、表格列、下拉选、弹框显示内容等。

3. 插槽的分类

默认插槽

子组件用 <slot> 标签确定渲染位置,标签里面可以放 DOM 结构。当父组件使用没有往插槽传入内容时,标签内的 DOM 结构会显示在页面。

具名插槽

子组件用 name 属性表示插槽的名字,不传则为默认插槽。父组件中在使用时在默认插槽的基础上加上 v-slot 属性或 #,值为子组件插槽 name 属性值。

子组件 Child.vue:

<template>
  <slot>插槽后备的内容</slot>
  <slot name="content">插槽后备的内容</slot>
</template>

父组件:

<child>
  <template v-slot:default>具名插槽</template>
  <!-- 具名插槽用插槽名做参数 -->
  <template v-slot:content>内容...</template>
</child>

作用域插槽

子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件 v-slot 接收的对象上。父组件中在使用时通过 v-slot:(简写:#)获取子组件的信息,在内容中使用。

子组件:

<template>
  <slot name="footer" :testProps="子组件的值">
    <h3>没传 footer 插槽</h3>
  </slot>
</template>

父组件:

<child>
  <!-- 把 v-slot 的值指定为作用域上下文对象 -->
  <template v-slot:default="slotProps">
    来自子组件数据:{{ slotProps.testProps }}
  </template>
  <template #default="slotProps">
    来自子组件数据:{{ slotProps.testProps }}
  </template>
</child>

4. 原理

slot 本质上是返回 VNode 的函数。一般情况下,Vue 中的组件要渲染到页面上需要经过 template -> render function -> VNode -> DOM 过程。插槽同样遵循这一过程:在父组件中解析插槽,生成对应的 VNode;在子组件渲染时把插槽对应的 VNode 渲染到指定位置。

来源整理自:vue3js.cn 面试官系列