浅析Vue中插槽slot的使用
插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。 实际上,一个slot最核心的两个问题在这里就点出来了,是显示不显示和怎样显示。
由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板和插槽模板两大类。
非插槽模板指的是html模板,比如‘div、span、ul、table’这些,非插槽模板的显示与隐藏以及怎样显示由组件自身控制;
插槽模板是slot,它是一个空壳子,因为它的显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置却由子组件自身决定,slot写在组件template的什么位置,父组件传过来的模板将来就显示在什么位置。
1、插槽内容
vue实现了一套内容分发的api,将 slot 元素作为承载内容分发的出口。
插槽内可以包含任何模板代码,包括html,以及其他组件。
如果组件内没有一个 slot 元素,那么该组件起始标签和结束标签之间的任何内容都会被抛弃。
2、编译作用域
规则:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
3、后备内容
有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。
很简单,就是默认值的概念:<slot>Submit</slot>
4、具名插槽
需要多个插槽的情况,slot 元素有一个特殊的属性:name,用来定义额外的插槽。一个不带 name 的 <slot> 出口会带有隐含的名字 “default”。
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以 v-slot 的参数的形式提供其名称:
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
现在 template 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 template 中的内容都会被视为默认插槽的内容。
注意:v-slot只能添加在一个 <template>
上(有一种例外),这一点和已废弃的slot特性不同
5、作用域插槽
<current-user>
{{ user.firstName }}
</current-user>
上述代码不会正常工作,因为只有 <current-user>
组件可以访问到 user
而我们提供的内容是在父级渲染的。为了让 user
在父级的插槽内容可用,我们可以将 user
作为 <slot>
元素的一个特性绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot>
元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot
带一个值来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
我们选择将包含所有插槽 prop 的对象命名为 slotProps
,但你也可以使用任意你喜欢的名字。
(1)独占默认插槽缩写方式:
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot
直接用在组件上,这也就是上面说的例外情况
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
注意:只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template>
的语法
(2)解构插槽:
作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里,这意味着 v-slot
的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式,所以可以利用ES6的解构来传入参数
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
解构:v-slot="{ user }"
重命名:v-slot="{ user: person }"
定义默认值:v-slot="{ user = { firstName: 'Guest' } }"
6、动态插槽名
<template v-slot:[dynamicSlotName]> ... </template>
7、缩写
v-slot:header
可以被重写为 #header
8、其他示例
主要来自官网学习整理:https://cn.vuejs.org/v2/guide/components-slots.html