在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot
指令)。它取代了slot
和slot-scope
这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。
1、插槽内容
实现方式:
父组件:
<component-slot>
<span style="font-size: 20px; color: red">hello </span>
</component-slot>
子组件:
<div style="display: flex; flex-direction: column">
<span style="font-size: 20px; color: blue">
我是自定义组件component-slot 下面显示slot插槽的内容
</span>
<slot></slot>
</div>
当组件渲染的时候,<slot></slot>
将会被替换为 <span style="font-size: 20px; color: red">hello </span> ,插槽内可以包含任何模板代码,包括 HTML\甚至其它的组件:l例如
<component-slot>
<slot-value></slot-value>
</component-slot>
注意事项:如果 <component-slot>
的 template
中没有包含一个 <slot>
元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
2、编译作用域
插槽只能访问父级作用域,不能访问子组件的作用域,父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
当你想在一个插槽中使用数据时,例如:
<navigation-link url="/profile">
Logged in as {{ user.name }}
</navigation-link>
该插槽跟模板的其它地方一样可以访问相同的实例 property (也就是相同的“作用域”),而不能访问 <navigation-link>
的作用域。例如 url
是访问不到的:
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
<!--
这里的 `url` 会是 undefined,因为其 (指该插槽的) 内容是
_传递给_ <navigation-link> 的而不是
在 <navigation-link> 组件*内部*定义的。
-->
</navigation-link>
3、后备内容
在子组件中slot标签中配置内容,作为后备内容,父组件中未设置slot内容时,显示子组件配置的slot内容,父组件中设置了slot内容,显示父组件的设置的内容
有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。例如在一个 <submit-button>
组件中:
<button type="submit">
<slot></slot>
</button>
我们可能希望这个 <button>
内绝大多数情况下都渲染文本“Submit”。为了将“Submit”作为后备内容,我们可以将它放在 <slot>
标签内:
<button type="submit">
<slot>Submit</slot>
</button>
现在当我在一个父级组件中使用 <submit-button>
并且不提供任何插槽内容时:
<submit-button></submit-button>
后备内容“Submit”将会被渲染:
<button type="submit">
Submit
</button>
但是如果我们提供内容:
<submit-button>
Save
</submit-button>
则这个提供的内容将会被渲染从而取代后备内容:页面渲染save会替换submit
<button type="submit">
Save
</button>
4、具名插槽(配置多个slot插槽)
自 2.6.0 起有所更新。已废弃的使用
slot
attribute 的语法在这里。
有时我们需要多个插槽。例如对于一个带有如下模板的 <base-layout>
组件:
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
</main>
<footer>
<!-- 我们希望把页脚放
对于这样的情况,<slot>
元素有一个特殊的 attribute:name
。这个 attribute 可以用来定义额外的插槽:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
一个不带 name
的 <slot>
出口会带有隐含的名字“default”。
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以 v-slot
的参数的形式提供其名称:
<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>
现在 <template>
元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot
的 <template>
中的内容都会被视为默认插槽的内容。
然而,如果你希望更明确一些,仍然可以在一个 <template>
中包裹默认插槽的内容:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
任何一种写法都会渲染出:
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
注意 v-slot
只能添加在 <template>
上 (只有一种例外情况),这一点和已经废弃的 slot
attribute 不同。