在Vue中,插槽(Slot)是一种强大的内容分发机制,允许父组件向子组件传递模板片段,从而实现更灵活的组件复用。根据使用场景和功能需求,插槽可分为以下三种类型:
1. 匿名插槽(默认插槽)
作用:用于接收父组件传递的默认内容,当子组件只需要一个插槽时使用。
子组件定义:
<!-- ChildComponent.vue -->
<template>
<div class="child">
<slot>默认内容(当父组件未提供时显示)</slot>
</div>
</template>
父组件使用:
<ChildComponent>
<p>父组件传递的内容</p>
</ChildComponent>
特点:
- 父组件内容会替换子组件中的
<slot>标签。 - 若父组件未提供内容,显示子组件
<slot>内的默认内容。
2. 具名插槽
作用:当子组件有多个插槽位置时,通过命名区分不同插槽。
子组件定义:
<!-- LayoutComponent.vue -->
<template>
<div class="layout">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> <!-- 匿名插槽,默认名为default -->
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
父组件使用:
<LayoutComponent>
<!-- 匿名插槽内容(对应默认插槽) -->
<template v-slot:default>
<p>主内容区域</p>
</template>
<!-- 具名插槽内容 -->
<template v-slot:header>
<h1>页面标题</h1>
</template>
<template v-slot:footer>
<p>版权信息</p>
</template>
</LayoutComponent>
语法注意:
- Vue 2.6+ 使用
v-slot:name,可简写为#name(如#header)。 - 匿名插槽的隐式名为
default,v-slot:default可省略。
3. 作用域插槽
作用:允许子组件向父组件传递数据,父组件根据数据动态渲染内容。
子组件定义:
<!-- TableComponent.vue -->
<template>
<table>
<tr v-for="(item, index) in items" :key="index">
<td>
<!-- 传递数据给父组件 -->
<slot :item="item" :index="index"></slot>
</td>
</tr>
</table>
</template>
<script>
export default {
props: ['items']
}
</script>
父组件使用:
<TableComponent :items="userList">
<template v-slot:default="slotProps">
<!-- 使用子组件传递的数据 -->
<span>{{ slotProps.item.name }} (ID: {{ slotProps.index }})</span>
</template>
</TableComponent>
语法简化:
- 对象解构:
<template v-slot:default="{ item, index }"> <span>{{ item.name }} ({{ index }})</span> </template>
版本差异与最佳实践
Vue 2 vs Vue 3
- Vue 2:
- 旧语法:
slot="name"和slot-scope="props"。 - 推荐升级到
v-slot语法(2.6+支持)。
- 旧语法:
- Vue 3:
- 完全支持
v-slot,移除旧语法。 - 作用域插槽数据传递更直观。
- 完全支持
最佳实践
- 明确命名:多插槽组件务必使用具名插槽,提升可读性。
- 作用域隔离:通过作用域插槽减少父子组件耦合,增强复用性。
- 动态插槽名(Vue 2.6+/3):
<template v-slot:[dynamicSlotName]> <!-- 内容 --> </template>
实际应用场景
- 通用布局组件:通过具名插槽定义页面的Header、Main、Footer。
- 数据驱动组件:如表单、表格使用作用域插槽,允许自定义渲染逻辑。
- UI库组件:如Element UI的
el-table通过作用域插槽暴露行数据。
总结
- 匿名插槽:基础内容分发,适合单一内容占位。
- 具名插槽:多插槽场景,明确内容位置。
- 作用域插槽:子向父传递数据,实现动态渲染。