插槽概念
“子组件” 为 “父组件” 提供的分发内容的出口。
在子组件中提供<slot></slot>标签,当父组件使用到子组件时,可在标签内部编写相关代码,子组件的slot标签会用来渲染父组件编写的相关代码。
父组件可以通过插槽添加任意代码,甚至其他组件。
<!-- 父组件 -->
<navigation-link url="/profile">
<!-- 可写其他组件 -->
<font-awesome-icon name="user"></font-awesome-icon>
Your Profile
</navigation-link>
如果子组件的template
中没有包含一个 <slot>
元素,则父组件在调用子组件时,起始标签和结束标签之间的任何内容都会被抛弃。
编译作用域
原则:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
默认内容
子组件slot标签内可编写默认内容,在父组件不提供插槽内容时,则展示默认内容,如果提供则被覆盖。
<!-- 子组件 -->
<button type="submit">
<!-- 默认展示 Submit -->
<slot>Submit</slot>
</button>
具名插槽
有时我们需要多个插槽,对于这样的情况,<slot>
元素有一个特殊的属性:name
。
一个不带 name
的 <slot>
出口会带有隐含的名字“default”。
<!-- 子组件 -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
<!-- 父组件 -->
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
作用域插槽
有时我们需要在父组件让插槽内容能够访问子组件中才有的数据。
<!-- 子组件 -->
<span>
<slot v-bind:user="user">
<!-- user是子组件中的数据 -->
{{ user.lastName }}
</slot>
</span>
<!-- 父组件 -->
<current-user>
<!-- 我们选择将包含所有插槽 prop 的对象命名为 slotData,这个名字是任意的。 -->
<template v-slot:default="slotData">
{{ slotData.user.firstName }}
</template>
</current-user>
# 独占默认插槽的缩写语法
<!-- 父组件 -->
<!-- 当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
注意:默认插槽的缩写语法不能和具名插槽混用。 只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template>
的语法。
# 解构插槽 Prop
作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里,这意味着 v-slot
的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。你也可以使用 解构来传入具体的插槽 prop。
<!-- 父组件 -->
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
<!-- 父组件 -->
<!-- 通过结构重新命名prop -->
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
<!-- 父组件 -->
<!-- 通过结构 给prop提供默认值 -->
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>