插槽(Slots)是 Vue.js 框架中的一个功能,允许在组件内部预留一些可替换的内容。通过插槽,可以给父组件填充模板代码,让父组件向子组件传递自定义的内容,以便在子组件中进行展示或处理。
1. 匿名插槽
Son.vue
<template>
<div>
<header class="header"></header>
<main class="main">
<slot></slot>
</main>
<footer class="footer"></footer>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.header {
height: 200px;
background-color: red;
color: white;
}
.main {
height: 300px;
background-color: blue;
color: white;
}
.footer {
height: 200px;
background-color: green;
color: white;
}
</style>
App.vue
<template>
<div class="content">
<Son>
<template v-slot>
<div>插入中间</div>
</template>
</Son>
</div>
</template>
<script setup lang="ts">
import Son from './components/Son.vue'
</script>
<style scoped>
</style>
2. 具名插槽
Son.vue
<template>
<div>
<header class="header">
<slot name="header"></slot>
</header>
<main class="main">
<slot></slot>
</main>
<footer class="footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.header {
height: 200px;
background-color: red;
color: white;
}
.main {
height: 300px;
background-color: blue;
color: white;
}
.footer {
height: 200px;
background-color: green;
color: white;
}
</style>
App.vue
<template>
<div class="content">
<Son>
<template v-slot:header>
<div>插入上面</div>
</template>
<template v-slot>
<div>插入中间</div>
</template>
<template v-slot:footer>
<div>插入下面</div>
</template>
</Son>
</div>
</template>
<script setup lang="ts">
import Son from './components/Son.vue'
</script>
<style scoped>
</style>
3. 插槽作用域
Son.vue
<template>
<div>
<header class="header">
<slot name="header"></slot>
</header>
<main class="main">
<div v-for="(item,index) in data">
<slot :index="index" :data="item"></slot>
</div>
</main>
<footer class="footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
type names = {
name: string,
age: number
}
const data = reactive<names[]>([
{
name: '张三',
age: 18
},
{
name: '李四',
age: 19
},
{
name: '王五',
age: 20
}
])
</script>
<style scoped>
.header {
height: 200px;
background-color: red;
color: white;
}
.main {
height: 300px;
background-color: blue;
color: white;
}
.footer {
height: 200px;
background-color: green;
color: white;
}
</style>
App.vue
<template>
<div class="content">
<Son>
<template v-slot:header>
<!-- 简写为:#header -->
<div>插入上面</div>
</template>
<!-- 直接解构出 data index -->
<template v-slot="{ data, index }">
<!-- 匿名插槽简写为:#default="{ data, index }" -->
<div>{{ data.name }}--{{ data.age }}--{{ index }}</div>
</template>
<template v-slot:footer>
<div>插入下面</div>
</template>
</Son>
</div>
</template>
<script setup lang="ts">
import Son from './components/Son.vue'
</script>
<style scoped></style>
4. 动态插槽
App.vue
<template>
<div class="content">
<Son>
<template v-slot:[name]>
<!-- 或者简写为:#[name] -->
<div>
我在哪儿?
</div>
</template>
</Son>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Son from './components/Son.vue'
let name = ref('footer')
// let name = ref('deault') // 插入中间的匿名插槽
</script>
<style scoped></style>