在 Vue 中,插槽(Slot)是一种强大的内容分发机制,允许你将父组件的内容灵活地注入到子组件的模板中。以下是 Vue 插槽的详细使用指南:
1. 基础插槽(默认插槽)
子组件(Child.vue)
<template>
<div class="child">
<h3>子组件标题</h3>
<slot></slot> <!-- 默认插槽,父组件内容将插入这里 -->
</div>
</template>父组件(Parent.vue)
<template>
<div>
<child>
<p>这是从父组件注入的内容</p> <!-- 替换子组件的 <slot> -->
</child>
</div>
</template>效果:父组件中的 <p> 标签会渲染到子组件的 <slot> 位置。
2. 具名插槽
当子组件需要多个插槽时,可通过 name 属性区分。
子组件(Child.vue)
<template>
<div class="child">
<header>
<slot name="header"></slot> <!-- 具名插槽 header -->
</header>
<main>
<slot></slot> <!-- 默认插槽 -->
</main>
<footer>
<slot name="footer"></slot> <!-- 具名插槽 footer -->
</footer>
</div>
</template>父组件(Parent.vue)
<template>
<child>
<template v-slot:header>
<h1>页面标题</h1> <!-- 注入到 header 插槽 -->
</template>
<p>默认内容</p> <!-- 注入到默认插槽 -->
<template #footer> <!-- # 是 v-slot: 的简写 -->
<p>页脚信息</p> <!-- 注入到 footer 插槽 -->
</template>
</child>
</template>关键点:
使用
v-slot:name或简写#name指定插槽名称。未命名的内容自动注入默认插槽。
3. 作用域插槽
子组件向插槽传递数据,父组件使用这些数据动态渲染内容。
子组件(Child.vue)
<template>
<div>
<slot :user="user" :count="count"></slot> <!-- 传递数据到插槽 -->
</div>
</template>
<script>
export default {
data() {
return {
user: { name: "Alice", age: 25 },
count: 10
};
}
};
</script>父组件(Parent.vue)
<template>
<child>
<template v-slot:default="slotProps">
<!-- 使用子组件传递的数据 -->
<p>用户名: {{ slotProps.user.name }}</p>
<p>年龄: {{ slotProps.user.age }}</p>
<p>计数: {{ slotProps.count }}</p>
</template>
</child>
</template>简写和解构:
<template>
<child>
<template #default="{ user, count }"> <!-- 解构数据 -->
<p>用户名: {{ user.name }}</p>
<p>计数: {{ count }}</p>
</template>
</child>
</template>关键点:
子组件通过
:prop="value"绑定数据到<slot>。父组件通过
v-slot:default="propsName"接收数据(propsName可自定义)。支持解构赋值简化代码。
4. 动态插槽名
动态绑定插槽名称(适用于动态场景)。
父组件(Parent.vue)
<template>
<child>
<template #[dynamicSlot]>
动态内容
</template>
</child>
</template>
<script>
export default {
data() {
return {
dynamicSlot: "header" // 动态插槽名
};
}
};
</script>关键点:
使用
v-slot:[name]或简写#[name]动态绑定插槽名。
5. 插槽后备内容
当父组件未提供插槽内容时,显示子组件定义的默认内容。
子组件(Child.vue)
<template>
<div>
<slot>
<p>默认后备内容</p> <!-- 父组件未提供内容时显示 -->
</slot>
</div>
</template>父组件(Parent.vue)
<template>
<child>
<!-- 未提供内容,显示后备内容 -->
</child>
</template>6. 注意事项
插槽作用域:
父组件插槽内容只能访问父组件的作用域(无法直接访问子组件数据)。
子组件通过作用域插槽传递数据给父组件。
命名规则:
插槽名支持 kebab-case(如
my-slot)和 camelCase(如mySlot)。动态插槽名需使用变量绑定。
Vue 版本差异:
Vue 2.6+:推荐使用
v-slot(取代旧版的slot和slot-scope)。Vue 3:语法与 Vue 2.6+ 一致,无重大变化。
最佳实践
默认插槽:用于简单内容分发。
具名插槽:用于组件布局结构(如头部/主体/页脚)。
作用域插槽:用于需要子组件数据的动态渲染(如列表渲染、表单控件)。
动态插槽:用于需要根据条件切换插槽的场景。
通过灵活使用插槽,你可以构建高度可复用、可扩展的 Vue 组件,实现优雅的内容分发逻辑。