插槽(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>
