Appearance
组件插槽
组件插槽是Vue3中的一个重要特性,它允许你在组件中定义可替换的内容区域。本章节将详细介绍Vue3中组件插槽的使用方法,包括默认插槽、具名插槽和作用域插槽。
什么是插槽?
插槽是Vue3中用于向组件传递内容的机制,它允许你在组件的模板中定义一些占位符,然后在使用组件时填充这些占位符。
默认插槽
1. 基本用法
默认插槽是最简单的插槽类型,它允许你向组件传递任意内容:
vue
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent>
<p>Hello from parent</p>
<button>Click me</button>
</ChildComponent>
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
</script>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h1>Child Component</h1>
<slot></slot>
</div>
</template>2. 默认内容
你可以为插槽提供默认内容,当父组件没有提供内容时会显示默认内容:
vue
<template>
<div class="child">
<h1>Child Component</h1>
<slot>
<p>Default content</p>
</slot>
</div>
</template>具名插槽
1. 基本用法
具名插槽允许你在组件中定义多个插槽,并为每个插槽指定一个名称:
vue
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent>
<template #header>
<h2>Header content</h2>
</template>
<template #main>
<p>Main content</p>
</template>
<template #footer>
<p>Footer content</p>
</template>
</ChildComponent>
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
</script>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<div class="header">
<slot name="header"></slot>
</div>
<div class="main">
<slot name="main"></slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
</div>
</template>
<style scoped>
.child {
border: 1px solid #ccc;
border-radius: 4px;
padding: 20px;
}
.header {
background-color: #f0f0f0;
padding: 10px;
margin-bottom: 10px;
}
.main {
padding: 10px;
margin-bottom: 10px;
}
.footer {
background-color: #f0f0f0;
padding: 10px;
}
</style>2. 简写语法
你可以使用简写语法 # 来表示具名插槽:
vue
<template>
<div>
<ChildComponent>
<template #header>
<h2>Header content</h2>
</template>
<template #main>
<p>Main content</p>
</template>
<template #footer>
<p>Footer content</p>
</template>
</ChildComponent>
</div>
</template>作用域插槽
1. 基本用法
作用域插槽允许子组件向父组件传递数据:
vue
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent>
<template #default="slotProps">
<p>Name: {{ slotProps.name }}</p>
<p>Age: {{ slotProps.age }}</p>
</template>
</ChildComponent>
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
</script>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h1>Child Component</h1>
<slot :name="user.name" :age="user.age"></slot>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const user = reactive({
name: 'John',
age: 25
})
</script>2. 解构赋值
你可以使用解构赋值来简化作用域插槽的使用:
vue
<template>
<div>
<ChildComponent>
<template #default="{ name, age }">
<p>Name: {{ name }}</p>
<p>Age: {{ age }}</p>
</template>
</ChildComponent>
</div>
</template>3. 具名作用域插槽
你可以为作用域插槽指定名称:
vue
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent>
<template #user="{ name, age }">
<p>Name: {{ name }}</p>
<p>Age: {{ age }}</p>
</template>
<template #item="{ item }">
<p>Item: {{ item.name }}</p>
</template>
</ChildComponent>
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
</script>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h1>Child Component</h1>
<slot name="user" :name="user.name" :age="user.age"></slot>
<slot name="item" :item="item"></slot>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
const user = reactive({
name: 'John',
age: 25
})
const item = ref({
name: 'Item 1'
})
</script>动态插槽名
你可以使用动态插槽名来动态选择插槽:
vue
<template>
<div>
<ChildComponent>
<template #[dynamicSlotName]>
<p>Dynamic slot content</p>
</template>
</ChildComponent>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
const dynamicSlotName = ref('header')
</script>插槽的最佳实践
1. 合理使用插槽
- 默认插槽:适合简单的内容传递
- 具名插槽:适合复杂的布局,如头部、主体、底部等
- 作用域插槽:适合需要子组件数据的场景
2. 保持插槽的清晰性
- 为具名插槽使用语义化的名称
- 为作用域插槽的 props 使用清晰的命名
- 避免过度使用插槽,保持组件的简洁性
3. 插槽的性能考虑
- 避免在插槽中使用复杂的表达式
- 对于频繁变化的内容,考虑使用响应式数据
- 合理使用默认内容,减少不必要的渲染
插槽的使用场景
1. 布局组件
vue
<template>
<div class="layout">
<header class="header">
<slot name="header"></slot>
</header>
<main class="main">
<slot></slot>
</main>
<footer class="footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<style scoped>
.layout {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.header {
background-color: #333;
color: white;
padding: 10px;
}
.main {
flex: 1;
padding: 20px;
}
.footer {
background-color: #333;
color: white;
padding: 10px;
text-align: center;
}
</style>2. 列表组件
vue
<template>
<div class="list">
<h2>{{ title }}</h2>
<ul>
<li v-for="item in items" :key="item.id">
<slot name="item" :item="item"></slot>
</li>
</ul>
</div>
</template>
<script setup>
defineProps({
title: String,
items: Array
})
</script>
<style scoped>
.list {
border: 1px solid #ccc;
border-radius: 4px;
padding: 20px;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 10px;
border-bottom: 1px solid #eee;
}
li:last-child {
border-bottom: none;
}
</style>3. 卡片组件
vue
<template>
<div class="card">
<div class="card-header">
<slot name="header"></slot>
</div>
<div class="card-body">
<slot></slot>
</div>
<div class="card-footer">
<slot name="footer"></slot>
</div>
</div>
</template>
<style scoped>
.card {
border: 1px solid #ccc;
border-radius: 4px;
overflow: hidden;
margin-bottom: 20px;
}
.card-header {
background-color: #f0f0f0;
padding: 15px;
border-bottom: 1px solid #ccc;
}
.card-body {
padding: 15px;
}
.card-footer {
background-color: #f0f0f0;
padding: 15px;
border-top: 1px solid #ccc;
}
</style>总结
组件插槽是Vue3中的一个重要特性,它允许你在组件中定义可替换的内容区域。通过默认插槽、具名插槽和作用域插槽,你可以实现各种复杂的布局和内容传递。
在使用插槽时,你应该合理选择插槽类型,保持插槽的清晰性,以及考虑插槽的性能。
在后续的章节中,我们将学习Vue3的组件生命周期,包括生命周期钩子的使用方法和最佳实践。
