Vue 组件插槽
Vue 组件插槽
简介
子组件能够通过 props
接收父组件传递的任意类型的 JavaScript 值在子组件中使用。
但组件要如何接收模板内容呢?
在某些场景中,可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。
类似 HTML 中通过元素的 html()
方法,向元素中添加另外一个元素或一个元素的组合(表格行及行中的列值)。
此时通过 props
就无法完成该需求,需要使用组件中的另一个概念插槽实现。
插槽内容与出口
Vue 提供一个 <slot></slot>
元素做为插槽的出口,使用 <slot>
作为一个占位符,将父组件传递进来的内容渲染在这里。
插槽内容可以是任意合法的模板内容,不局限于文本,可以传入多个元素,甚至是组件。
并且,插槽内可以有默认内容,如果在使用组件时没有为插槽提供内容,则渲染默认内容。
通过使用插槽,组件更加灵活和具有可复用性。现在组件可以用在不同的地方渲染各异的内容,但同时还保证都具有相同的样式。
SlotOC.vue
<template>
<p>被用在插槽中的组件</p>
</template>
SlotSC.vue
<template>
<hr>
<h2>这是一个具有插槽的组件,下面是插槽中的内容</h2>
<slot><h4>这是插槽默认内容</h4></slot>
<hr>
</template>
SlotFC.vue
<script setup>
import SlotOC from './SlotOC.vue';
import SlotSC from './SlotSC.vue';
</script>
<template>
<h1>这是父组件内容</h1>
<SlotSC> 这是向子组件插槽中添加的一段文本 </SlotSC>
<SlotSC>
<div>
<ul>
<li>这是向子组件插槽中添加的一个复合HTML元素1</li>
<li>这是向子组件插槽中添加的一个复合HTML元素2</li>
<li>这是向子组件插槽中添加的一个复合HTML元素3</li>
</ul>
</div>
</SlotSC>
<SlotSC>
<SlotOC></SlotOC>
</SlotSC>
</template>
App.vue
<script setup>
import SlotFC from './components/MyComponents/SlotFC.vue';
</script>
<template>
<SlotFC></SlotFC>
</template>
具名插槽
有些情况下,一个组件中需要包含多个插槽,此时在使用该组件向插槽中传递数据时,如何区别哪个数据放在哪个插槽中呢?
对于这种场景,<slot>
元素可以设置一个特殊的属性 name
,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容。
没有提供 name
的插槽会被隐式的命名为 default
。
<!-- 具名插槽 -->
<slot name="sloatname"></slot>
<!-- 未具名插槽,默认名为 default -->
<slot></slot>
v-slot
要为具名插槽传入内容,我们需要使用一个含 v-slot
指令的 <template>
元素,并将目标插槽的名字传给该指令。
当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 <template>
节点都被隐式地视为默认插槽的内容。
v-slot
指令也可以简写为 #
。
<!-- 标准形式 -->
<template v-slot:sloatname></template>
<!-- 简写形式 -->
<template #sloatname></template>
SlotnameSC.vue
<template>
<hr>
<h2>这是一个具有插槽的组件,下面是插槽中的内容</h2>
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
<hr>
</template>
SlotnameFC.vue
<script setup>
import SlotnameSC from './SlotnameSC.vue';
</script>
<template>
<h1>这是父组件内容</h1>
<SlotnameSC>
<template v-slot:header>
<h1>这是页面标题</h1>
</template>n
<template #default>
<p>这是内容显示区域</p>
<p>用来显示文本和图片</p>
</template>
<!-- <p>这是内容显示区域</p>
<p>用来显示文本和图片</p> -->
<template #footer>
<p>这里显示页脚信息</p>
</template>
</SlotnameSC>
</template>
App.vue
<script setup>
import SlotnameFC from './components/MyComponents/SlotnameFC.vue';
</script>
<template>
<SlotnameFC></SlotnameFC>
</template>
总结
- 组件中除能显示
props
接收的数据外,还可以通过<slot></slot>
设置一个插槽占位符,用来接收需要渲染的内容。 - 插槽中除文本外,还可以渲染元素,甚至是一个组件
- 一个组件中可以有多个插槽,通过
name
属性为插槽具名。 - 为具名插槽传递数据时,需要配合使用
template
元素。并使用属性v-slot:slotname
或#slotname
方式指定插槽。