vue3插槽详解
在vue3中,插槽(Slot)的核心概念是为子组件预留内容分发的占位符,让父组件可以传入自定义的模板片段。
各类插槽核心使用场景
以下是一个综合了上述各类插槽的示例,包含一个复杂的 ArticleLayout 组件和一个使用它的父组件。
1. 子组件:ArticleLayout.vue
这个组件展示了多种插槽的混合使用。
<template>
<article class="article-layout">
<!-- 动态插槽:根据条件动态决定头部插槽 -->
<header>
<slot :name="headerSlotName" :title="articleTitle"></slot>
</header>
<!-- 默认插槽:用于文章主体内容 -->
<main>
<slot>这是默认的主内容,父组件没传内容时显示。</slot>
</main>
<!-- 具名插槽:用于作者信息 -->
<footer>
<slot name="footer"></slot>
</footer>
<!-- 作用域插槽:渲染相关文章列表,父组件决定如何渲染 -->
<aside>
<h3>相关推荐</h3>
<ul>
<li v-for="related in relatedList" :key="related.id">
<!-- 子组件将 related 对象作为 prop 传递给父组件 -->
<slot name="related" :related="related"></slot>
</li>
</ul>
</aside>
</article>
</template>
<script setup>
import { ref, computed } from 'vue'
// 定义组件接收的属性
const props = defineProps({
articleTitle: String,
relatedList: {
type: Array,
default: () => []
}
})
// 动态计算头部插槽名称
const headerSlotName = computed(() => {
return props.articleTitle ? 'header' : 'default-header'
})
</script>
2. 父组件:ParentComponent.vue
这个组件展示了如何向子组件的各个插槽填充内容,特别是如何使用作用域插槽接收数据。
vue
<template>
<ArticleLayout
:article-title="articleData.title"
:related-list="relatedArticles"
>
<!-- 动态插槽内容:根据子组件计算的 headerSlotName 填充 -->
<!-- 同时接收子组件传递的 title 数据 -->
<template #[headerSlotName]="{ title }">
<h1>{{ title || '默认标题' }}</h1>
<p class="publish-time">发布时间: {{ currentTime }}</p>
</template>
<!-- 覆盖默认插槽 -->
<p>{{ articleData.content }}</p>
<img :src="articleData.imageUrl" alt="文章配图">
<!-- 具名插槽:填充页脚 -->
<template #footer>
<div class="article-footer">
<span>作者: {{ authorName }}</span>
<button @click="likeArticle">点赞</button>
</div>
</template>
<!-- 作用域插槽:接收子组件传递的 related 数据,自定义渲染 -->
<template #related="{ related }">
<!-- 父组件可以完全控制如何渲染每一项 -->
<div class="related-item">
<h4>{{ related.title }}</h4>
<p>{{ related.summary }}</p>
<span class="read-count">阅读量: {{ related.views }}</span>
</div>
</template>
</ArticleLayout>
</template>
<script setup>
import { ref, computed } from 'vue'
import ArticleLayout from './ArticleLayout.vue'
// 假设的数据
const articleData = ref({
title: 'Vue 3 插槽详解',
content: '这是一篇关于Vue 3插槽使用的详细教程...',
imageUrl: '/path/to/image.jpg'
})
const relatedArticles = ref([
{ id: 1, title: 'Vue 3 组合式API', summary: '学习组合式API...', views: 1200 },
{ id: 2, title: 'Vue 3 响应式原理', summary: '深入理解响应式...', views: 980 }
])
const authorName = ref('技术博主')
const currentTime = computed(() => new Date().toLocaleDateString())
// 动态插槽名
const headerSlotName = ref('header')
const likeArticle = () => {
console.log('文章已点赞')
// 点赞逻辑
}
</script>
重点变化总结
| 特性 | Vue 2 | Vue 3 |
|---|---|---|
| 语法 | slot-scope | v-slot |
| 简写 | 无 | # |
| 具名插槽+作用域 | slot="name" slot-scope="props" | #name="props" |
| 默认插槽作用域 | slot-scope="props" | #default="props" |
| 解构支持 | ✅ | ✅ |