1、先说一下具名插槽
有时在一个组件中包含多个插槽出口是很有用的。举例来说,在一个 组件中,有如下模板:
<div class="container">
<header>
<!-- 标题内容放这里 -->
</header>
<main>
<!-- 主要内容放这里 -->
</main>
<footer>
<!-- 底部内容放这里 -->
</footer>
</div>
对于这种场景,<slot>
元素可以有一个特殊的 attribute name,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
这类带 name 的插槽被称为具名插槽
(named slots)。没有提供 name 的 出口会隐式地命名为“default”
要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素
,并将目标插槽的名字传给该指令:
<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>
v-slot
有对应的简写 #
,因此 可以简写为 <template #header>。其意思就是“将这部分模板片段传入子组件的 header
插槽中”。
下面我们给出完整的、向 传递插槽内容的代码,指令均使用的是缩写形式:
<BaseLayout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</BaseLayout>
2、作用域插槽
使用场景:
数据在组件的自身,但根据数据生成的结构需要组件的使用者
来决定。
<!-- <MyComponent> 的模板 -->
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
使用者:
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
我们可以将其类比为一个函数,函数名为default
MyComponent({
// 类比默认插槽,将其想成一个函数
default: (slotProps) => {
return `${slotProps.text} ${slotProps.count}`
}
})
function MyComponent(slots) {
const greetingMessage = 'hello'
return `<div>${
// 在插槽函数调用时传入 props
slots.default({ text: greetingMessage, count: 1 })
}</div>`
}
3、具名作用域插槽
使用者:
<FancyList :api-url="url" :per-page="10">
// 使用格式:
// 1、(简写)#插槽名='传过来的值'
// 2、(非简写)v-slot:插槽名字 ='传过来的值'
<template #item="{ body, username, likes }"> // 这里对传过来的值进行了解构
<div class="item">
<p>{{ body }}</p>
<p>by {{ username }} | {{ likes }} likes</p>
</div>
</template>
</FancyList>
在 之中,我们可以多次渲染 并每次都提供不同的数据 (注意我们这里使用了 v-bind 来传递插槽的 props):
<ul>
<li v-for="item in items">
<slot name="item" v-bind="item"></slot>
</li>
</ul>