在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段,为此 vue 提供了组件的插槽。
一、什么是插槽
在封装组件时,可以使用<slot>元素把不确定的、希望由用户指定的部分定义为插槽;插槽可以理解为给预留的内容提供占位符。
插槽也可以提供默认内容,如果组件的使用者没有为插槽提供任何内容,则插槽内的默认内容会生效。
注意:如果在封装组件时没有预留任何<slot>插槽,用户提供传递一些模板片段将会被遗弃。

二、插槽实例
Card.vue
<script setup>
</script>
<template>
<div class="card">
<h2 class="title"></h2>
<div class="subtitle"></div>
<div class="content"></div>
<div class="action">
<!-- 定义一个插槽 -->
<!-- 插槽的默认内容,只有没有提供内容时,才会显示 -->
<slot>卡片功能区域</slot>
</div>
</div>
</template>
<style>
.card {
width: 250px;
border: 1px solid black;
}
.card h2,
.card div {
margin: 10px;
padding: 5px;
}
.title {
border: 1px solid red;
}
.subtitle {
border: 1px solid green;
}
.content {
border: 1px solid blue;
}
.action {
border: 1px solid pink;
}
</style>
App.vue
<script setup>
import CardVue from './components/Card.vue'
</script>
<!-- 视图区域(view) -->
<template>
<CardVue>
<!-- 向子组件插槽中提供内容 -->
<button>关闭</button>
</CardVue>
</template>
三、具名插槽
1、如果在封装组件时需要预留多个插槽节点,则需要为每个<slot>插槽指定具体的name名称,这种带有具体名称的插槽叫做“具名插槽”
2、没有指定name名称的插槽,会有隐含的名称叫做 default
3、在"<template>"元素上使用 v-slot:slotName或者#slotName向指定的具名插槽提供内容
实例:
Card.vue
<script setup>
</script>
<template>
<div class="card">
<h2 class="title">
<!-- 带有name属性的插槽,称为具名插槽 -->
<slot name="cardTitle"></slot>
</h2>
<div class="subtitle">
<slot name="cardSubtitle"></slot>
</div>
<div class="content">
<slot name="cardContent"></slot>
</div>
<div class="action">
<!-- 定义一个插槽 -->
<!-- 插槽的默认内容,只有没有提供内容时,才会显示 -->
<!-- 没有name属性的插槽称为默认插槽,会有一个隐含的名字:default -->
<slot>卡片功能区域</slot>
</div>
</div>
</template>
<style>
.card {
width: 250px;
border: 1px solid black;
}
.card h2,
.card div {
margin: 10px;
padding: 5px;
}
.title {
border: 1px solid red;
}
.subtitle {
border: 1px solid green;
}
.content {
border: 1px solid blue;
}
.action {
border: 1px solid pink;
}
</style>
App.vue
<script setup>
import CardVue from './components/Card.vue'
</script>
<!-- 视图区域(view) -->
<template>
<CardVue>
<!-- 向具名插槽提供内容 -->
<template v-slot:cardTitle>
博客
</template>
<template #cardSubtitle>
<i>百万博主分享经验</i>
</template>
<!-- 向默认插槽提供内容 -->
<template #default>
<button>关闭</button>
</template>
</CardVue>
</template>
四、作用域插槽
如何在向插槽提供的内容时获得子组件域内的数据呢?
1、在声明插槽时使用属性值的方式来传递子组件的数据,这种带有数据的插槽称之为作用域插槽
2、在"<template>"元素上使用v-slot:slotName="slotProps"或#slotName="slotProps"的方式来访问插槽传递属性值
3、如果没有使用"<template>"元素,而是直接在使用子组件中直接给默认插槽提供内容,我们可以在使用该子组件时用v-slot="slotProps"来接收该插槽传递的数据对象
注意:插槽上的name是一个Vue特别保留的属性,不会在作用域插槽中访问到
Card.vue
<script setup>
import { reactive,ref } from 'vue';
let blog = reactive({
title: 'Java的选择结构',
time: '2023-07-09 12:20:30'
})
let author = ref('爱学习的人')
let closeBth = ref('关闭')
let determine = ref('确定')
</script>
<template>
<div class="card">
<h2 class="title">
<!-- 带有name属性的插槽,称为具名插槽 -->
<slot name="cardTitle"></slot>
</h2>
<div class="subtitle">
<slot name="cardSubtitle"></slot>
</div>
<div class="content">
<!-- 带有数据的插槽称之为作用域插槽 -->
<!-- <slot>插槽上的name是一个Vue特别保留的属性,不会在作用域插槽中访问到 -->
<slot name="cardContent" :cardBlog="blog" :cardAuthor="author"></slot>
</div>
<div class="action">
<!-- 定义一个插槽 -->
<!-- 插槽的默认内容,只有没有提供内容时,才会显示 -->
<!-- 没有name属性的插槽称为默认插槽,会有一个隐含的名字:default -->
<slot :close="closeBth" :sure="determine">卡片功能区域</slot>
</div>
</div>
</template>
<style>
.card {
width: 250px;
border: 1px solid black;
}
.card h2,
.card div {
margin: 10px;
padding: 5px;
}
.title {
border: 1px solid red;
}
.subtitle {
border: 1px solid green;
}
.content {
border: 1px solid blue;
}
.action {
border: 1px solid pink;
}
</style>
App.vue
<script setup>
import CardVue from './components/Card.vue'
</script>
<!-- 视图区域(view) -->
<template>
<CardVue>
<!-- 向具名插槽提供内容 -->
<template v-slot:cardTitle>
博客
</template>
<template #cardSubtitle>
<i>百万博主分享经验</i>
</template>
<!-- 访问插槽中提供的数据 -->
<template #cardContent="dataProps">
<ul>
<li>{{ dataProps }}</li>
<li>博客的标题:{{ dataProps.cardBlog.title }}</li>
<li>博客的时间:{{ dataProps.cardBlog.time }}</li>
<li>博主:{{ dataProps.cardAuthor }}</li>
</ul>
</template>
<!-- 向默认插槽提供内容 -->
<template #default>
<button>关闭</button>
</template>
</CardVue>
<hr>
<CardVue v-slot="dataProps">
<!-- 如果使用子组件时用到了v-slot,则该子组件标签中将无法向其他具名插槽中提供内容 -->
<!-- <template #cardSubtitle>
<i>百万博主分享经验</i>
</template> -->
<button>{{ dataProps.close }}</button>
<button>{{ dataProps.sure }}</button>
</CardVue>
</template>
1977

被折叠的 条评论
为什么被折叠?



