前言
在组件化开发中,插槽 (Slot)是实现内容分发(Content Distribution)的核心机制。它允许我们将组件的“外壳”与“内容”解耦,让组件具备极高的扩展性。
一、 什么是插槽?
插槽是子组件提供给父组件的“占位符”,用<slot></slot>标签表示。父组件传递的任何模板代码(HTML、组件等)都会替换子组件中的<slot>标签。
二、 插槽的三大类型
1. 默认插槽 (Default Slot)
最基础的插槽,不需要定义name属性。
- 特点:一个子组件通常只建议使用一个默认插槽。
示例:
<!-- 子组件 --> <template> <div class="card"> <div class="card-title">通用卡片标题</div> <div class="card-content"> <slot> 这里是默认的填充文本 </slot> </div> </div> </template><!-- 父组件 --> <template> <div class="app"> <MyCard> 这是我传递给卡片的具体内容。 </MyCard> </div> </template>2. 具名插槽 (Named Slots)
当子组件需要多个占位符时,通过name属性来区分。
- 语法糖:
v-slot:header可以简写为#header。
示例:
<!-- 子组件:LayoutComponent.vue --> <template> <div class="layout"> <header class="header"> <slot name="header"></slot> </header> <main class="content"> <slot></slot> </main> <footer class="footer"> <slot name="footer"></slot> </footer> </div> </template> <script setup lang="ts"> <!-- Vue 3 Composition API 模式下,逻辑部分可以保持简洁 --> </script><!-- 父组件使用示例 --> <template> <LayoutComponent> <template #header> <h1>页面标题</h1> <nav>导航菜单</nav> </template> <p>这是主体内容,将填充到默认插槽中...</p> <template #footer> <p>版权信息 © 2026</p> </template> </LayoutComponent> </template> <script setup lang="ts"> import LayoutComponent from './LayoutComponent.vue'; </script>3. 作用域插槽 (Scoped Slots)
核心价值:“子传父”的特殊形式。子组件将内部数据绑定在<slot>上,父组件在填充内容时可以接收并使用这些数据。
示例:
<!-- 子组件:`UserList.vue` --> <template> <ul> <li v-for="user in users" :key="user.id"> <slot :user="user" :index="user.id"> {{ user.name }} </slot> </li> </ul> </template> <script setup lang="ts"> interface User { id: number; name: string; role: string; } const users: User[] = [ { id: 1, name: '张三', role: '管理员' }, { id: 2, name: '李四', role: '开发者' } ]; </script><!-- 父组件使用示例 --> <template> <UserList> <template #default="{ user }"> <span :style="{ color: user.role === '管理员' ? 'red' : 'blue' }"> {{ user.name }} - 【{{ user.role }}】 </span> </template> </UserList> </template>三、 补充:插槽的默认内容
在子组件中,你可以在<slot>标签内部放置内容。如果父组件没有提供任何插槽内容,则会渲染这些“后备内容”;如果提供了,则会被覆盖。
<slot>这是如果没有内容时显示的默认文本</slot>四、 总结:如何选择插槽?
| 插槽类型 | 使用场景 |
|---|---|
| 默认插槽 | 组件只有一个扩展点时使用。 |
| 具名插槽 | 组件有多个固定区域(如 Header/Main/Footer)需要自定义时使用。 |
| 作用域插槽 | 需要根据子组件的内部数据来决定父组件渲染样式的场景(如列表展示)。 |