最近忙着写一些组件,关于插槽这一块自己还是用着 slot 和 slot-scope,然后看了一下文档的更新,于是又重新把“插槽”学习了一篇,下面一段是文档中的说明:
在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot
指令)。它取代了slot
和slot-scope
这两个目前已被废弃但未被移除且仍在文档中的特性。新语法的由来可查阅这份 RFC。
插槽,也就是 slot,slot 就是子组件里的一个占位符,一个 slot 的核心问题,就是显不显示,显示的话显示话,该如何去展示出来,这是由父组件所控制的,但是插槽显示的位置是由子组件自己所决定的,slot 写在组件 template 的什么位置,父组件传过来的模板将会显示在什么位置。
插槽的基本使用方法(匿名插槽)
这是一个子组件,我们使用了默认插槽(匿名插槽),父组件的内容将会代替 <slot></slot> 显示出来
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {name: 'children'}
</script>
// 使用 children 组件
<children> 代替 slot 的内容 </children>
渲染后的结果
<template>
<div>
代替 slot 的内容
</div>
</template>
具名插槽
自 2.6.0 起有所更新。已废弃的使用
slot
特性的语法在这里。
有时我们一个组件里面需要多个插槽。我们怎么来区分多个 slot,而且不同 slot 的显示位置也是有差异的. 对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:
- 注意: 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
如下面一个组件, 需要多个插槽。如何向组件提供内容呢?
<template>
<div>
<header>
<slot name="header"></slot>
<slot></slot>
</header>
<main>
<slot></slot>
</main>
</div>
</template>
在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
<!-- old -->
<children>
<template slot="header">
<h1>Here might be a page title</h1>
</template>
<template slot="default">
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
</children>
<!-- new -->
<children>
<template v-slot:header>
<!-- <template #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>
</children>
渲染后的结果
<template>
<div>
<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>
</div>
</template>
- 注意:
v-slot
只能添加在一个<template>
上 (只有一种例外情况),这一点和已经废弃的slot
特性不同。 - 例外情况: 当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上:
作用域插槽
自 2.6.0 起有所更新。已废弃的使用
slot-scope
特性的语法在这里。
有时候,插槽的内容中有需要访问到子组件里面的内容,类似子组件里的 slot 可以绑定一些当前作用域,从而传出来,使用组件时,插槽的内容就可以拿到 slot 传出来的数据, 父级的插槽内容可用。
如下,让后备内容(slot 默认内容)user.firstName 替换正常情况下的 user.lastName
<span>
<slot>
{{user.lastName}}
</slot>
</span>
绑定在 <slot> 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:
// slot 绑定了当前作用域下 user 对象
// 为什 slot 中还有内容呢?不是由插槽内容填充吗?在 slot 中有内容,我们可以称之为后备内容,就是 slot 的默认内容,但我们使用这个插槽时,却没有内容填充,就会显示其默认的内容。<span>
<slot v-bind:user="user">
{{user.lastName}}
</slot>
</span>
在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字,slotProps 可以任意命名的,通过 slotProps.use 就拿到了子组件 slot 传出来的对象。
<!-- old -->
<children>
<template slot="default" slot-scope="slotProps">
{{slotProps.user.firstName}}
</template>
</children>
<!-- new -->
<children>
<template v-slot:default="slotProps">
{{slotProps.user.firstName}}
</template>
</children>
在上述情况下,当被提供的内容只有默认插槽时,这样我们就可以把 v-slot 直接用在组件上:
<children v-slot:default="slotProps">
{{slotProps.user.firstName}}
</children>
// default 可以省略, 默认插槽的缩写语法
<children v-slot="slotProps">
{{slotProps.user.firstName}}
</children>
<!-- 解构插槽 prop -->
<childrenv-slot="{user}">
{{user.firstName}}
</children>
<!-- user 重命名为 person-->
<childrenv-slot="{user: person}">
{{person.firstName}}
</children>
- 注意: 默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确, 只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法
后备内容
什么是后备内容呢,一个 slot 有它的默认的内容,有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。
总结
这里只是简单描述了几个关键点,其实还有很多可扩展的,或其他特性,我们还是需要多去看文档,多学习。