Vue 提供 插槽(Slot) 机制,使组件可以更灵活地复用和拓展内容。插槽允许父组件向子组件传递结构化的内容。
1. 默认插槽(Default Slot)
默认插槽允许父组件传递内容到子组件的特定位置。
<!-- ChildComponent.vue -->
<template>
<div class="box">
<slot>默认内容</slot>
</div>
</template>
<style>
.box { padding: 10px; border: 1px solid #ddd; }
</style>
<!-- Parent.vue -->
<template>
<ChildComponent>
<p>我是父组件传递的内容</p>
</ChildComponent>
</template>
结果:
<div class="box">
<p>我是父组件传递的内容</p>
</div>
- 如果
ChildComponent
没有提供插槽内容,slot
的默认内容(默认内容
)会显示。 - 但如果
Parent.vue
提供了内容,则它会替换slot
位置的默认内容。
2. 具名插槽(Named Slots)
具名插槽用于多个插槽的情况,允许父组件向不同位置插入不同的内容。
<!-- ChildComponent.vue -->
<template>
<div class="box">
<header><slot name="header">默认标题</slot></header>
<main><slot>默认内容</slot></main>
<footer><slot name="footer">默认页脚</slot></footer>
</div>
</template>
<!-- Parent.vue -->
<template>
<ChildComponent>
<template #header>
<h1>我是自定义标题</h1>
</template>
<p>我是主要内容</p>
<template #footer>
<small>我是自定义页脚</small>
</template>
</ChildComponent>
</template>
结果:
<div class="box">
<header><h1>我是自定义标题</h1></header>
<main><p>我是主要内容</p></main>
<footer><small>我是自定义页脚</small></footer>
</div>
#header
和#footer
代表对应的具名插槽,只有p
直接放入的内容属于默认插槽。
3. 作用域插槽(Scoped Slot)
作用域插槽允许子组件将 数据 传递给父组件,以便父组件可以决定如何渲染内容。
<!-- ChildComponent.vue -->
<template>
<div>
<slot :user="userData"></slot>
</div>
</template>
<script>
export default {
data() {
return {
userData: { name: "Alice", age: 25 }
};
}
};
</script>
<!-- Parent.vue -->
<template>
<ChildComponent v-slot="{ user }">
<p>用户名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
</ChildComponent>
</template>
结果:
<div>
<p>用户名:Alice</p>
<p>年龄:25</p>
</div>
- 子组件
ChildComponent.vue
通过slot
传递userData
数据。 - 父组件
Parent.vue
通过v-slot="{ user }"
结构解构user
并使用它。
简写:
<ChildComponent #default="{ user }">
<p>用户名:{{ user.name }}</p>
</ChildComponent>
4. 具名作用域插槽(Scoped Named Slot)
可以结合具名插槽和作用域插槽。
<!-- ChildComponent.vue -->
<template>
<div>
<slot name="profile" :user="userData"></slot>
</div>
</template>
<!-- Parent.vue -->
<template>
<ChildComponent>
<template #profile="{ user }">
<p>用户信息:{{ user.name }},年龄 {{ user.age }}</p>
</template>
</ChildComponent>
</template>
结果:
<div>
<p>用户信息:Alice,年龄 25</p>
</div>
- 子组件的
slot name="profile"
传递userData
。 - 父组件
#profile="{ user }"
绑定数据,并自定义显示方式。
5. 动态插槽名
如果插槽名是动态的,可以用 :name
绑定。
<!-- ChildComponent.vue -->
<template>
<div>
<slot :name="dynamicSlot" />
</div>
</template>
<script>
export default {
data() {
return {
dynamicSlot: "content"
};
}
};
</script>
<!-- Parent.vue -->
<template>
<ChildComponent>
<template #content>
<p>这是动态插槽的内容</p>
</template>
</ChildComponent>
</template>
总结
插槽类型 | 语法 | 用途 |
---|---|---|
默认插槽 | <slot></slot> | 允许父组件传递内容 |
具名插槽 | <slot name="xxx"></slot> | 允许多个插槽分别填充不同内容 |
作用域插槽 | <slot :prop="data"></slot> | 子组件提供数据,父组件决定如何渲染 |
具名作用域插槽 | <slot name="xxx" :prop="data"></slot> | 结合具名插槽和作用域插槽 |
动态插槽 | <slot :name="slotName"></slot> | 插槽名动态可变 |