插槽(slot)可以理解为对 Vue 组件的扩展,我们可以通过插槽向组件内部的指定位置传递内容,也可以实现父子组件传参。
简单的插槽
组件 NavigationLink
定义如下:
<template>
<a :href="url">
<slot></slot>
</a>
</template>
<script>
export default {
name: "NavigationLink",
props: ['url']
}
</script>
使用该组件时,在标签对之间输入一些文字,如下:
<NavigationLink url="/home">首页</NavigationLink>
当组件渲染的时候,<slot></slot>
将会被替换为“首页”。如果组件 NavigationLink
中没有定义插槽,则该组件标签对之间的任何内容都会被抛弃。
也可以为插槽设置默认内容,它会在标签对之间的内容为空时被渲染。例如在 SubmitButton
组件中,希望它默认显示文本“Submit”,可以指定插槽的默认内容。
<template>
<button type="submit">
<slot>Submit</slot>
</button>
</template>
<script>
export default {
name: "SubmitButton"
}
</script>
具名插槽
有时我们需要在一个组件中设置多个插槽,例如下面这样的组件:
<div class="container">
<header>
<!-- 把页头放这里 -->
</header>
<main>
<!-- 把主要内容放这里 -->
</main>
<footer>
<!-- 把页脚放这里 -->
</footer>
</div>
对于这样的情况,可以给插槽 <slot>
指定一个 name
属性,该属性用来匹配有对应特征的元素。
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot>未显示给出 name 属性,默认其值为 "default"</slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
我们可以在 <template>
标签上使用 v-slot
指令,以下面的形式为其指定名称。
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template>
<p>A paragraph for the main content.</p>
<p>未指定 "v-slot",将其视为 "default"</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
同 v-on
和 v-bind
一样,v-slot:
可简化为 #
,比如 v-slot:header
可简写为 #header
。
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>不指定 v-slot 时,可省略外层的 <template> 标签</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
插槽的 props
我们可以将插槽看作一个组件,它也有自己的 props。例如下面的组件 ShowText
,它默认显示 user
的 lastName
,而父组件希望它显示 user
的 firstName
。
<template>
<p>
<slot v-bind:user="user">
{{user.lastName}}
</slot>
</p>
</template>
<script>
export default {
name: "ShowText",
data() {
return {
user: {
firstName: "Tom",
lastName: "Smith"
}
}
}
}
</script>
给插槽的 props 绑定一个 user
,父组件以以下形式令其显示 user
的 firstName
。
<ShowText>
<template v-slot:default="slotProps">
{{slotProps.user.firstName}}
</template>
</ShowText>
上例中,
slotProps
是给插槽的 props 定义的名字,方便父组件访问其 props。
也可以使用 ES2015 的解构特性来传入具体的插槽 prop,如下:
<ShowText>
<template v-slot:default="{user}">
{{user.firstName}}
</template>
</ShowText>
可以为某个 prop 重命名,例如将 user
重命名为 person
:
<ShowText>
<template v-slot:default="{user: person}">
{{person.firstName}}
</template>
</ShowText>
甚至可以定义其默认内容,用于插槽 props 是 undefined
的情形,如下:
<ShowText>
<template v-slot:default="{user = {firstName: 'Guest'}}">
{{user.firstName}}
</template>
</ShowText>
动态的插槽名
以如下的形式定义动态的插槽名。
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>