
九、Vue插槽
一、为什么使用 Slot
开发中,会经常封装一个个可复用的组件
前面通过 props 传递给组件一些数据,让组件来进行展示
- 但是为了让这个组件具备更强的通用性,不能将组件中的内容限制为固定的 div、span 等等这些元素
- 比如某种情况下我们使用组件,希望组件显示的是一个按钮,某种情况下使用组件希望显示的是一张图片
- 应该让使用者可以决定某一块区域到底存放什么内容和元素
举个栗子:假如定制一个通用的导航组件 - NavBar
- 这个组件分成三块区域:左边-中间-右边,每块区域的内容是不固定
- 左边区域可能显示一个菜单图标,也可能显示一个返回按钮,可能什么都不显示; 中间区域可能显示一个搜索框,也可能是一个列表,也可能是一个标题,等等;右边可能是一个文字,也可能是一个图标,也可能什么都不显示
二、使用 Slot
插槽的使用过程其实是抽取共性、预留不同
将共同的元素、内容依然在组件内进行封装
同时将不同的元素使用 slot 作为占位,让外部决定到底显示什么样的元素
- Vue 中将 slot 元素作为承载分发内容的出口
- 在封装组件中,使用特殊的元素就可以为封装组件开启一个插槽
- 该插槽插入什么内容取决于父组件如何使用
Slot.vue 定义插槽
1 | <template> |
App.vue 使用插槽
1 | <template> |
插入普通的内容、html 元素、组件元素,都可以是可以的
默认的内容只会在没有提供插入的内容时,才会显示
具名插槽
如果定义了多个插槽,且插入了多个元素,会怎么进行展示?
1 | <template> |
默认情况下每个插槽都会获取到我们插入的内容来显示
希望达到的效果是插槽对应的显示,这个时候我们就可以使用 具名插槽
具名插槽顾名思义就是给插槽起一个名字, 元素有一个特殊的 attribute:name
一个不带 name 的 slot,会带有隐含的名字 default
动态插槽名
目前使用的插槽名称都是固定的
比如 v-slot:left、v-slot:center 等等
可以通过 v-slot:[dynamicSlotName]方式动态绑定一个名称
1 | <template v-slot:[name]></template> |
具名插槽缩写
跟 v-on 和 v-bind 一样,v-slot 也有缩写
即把参数之前的所有内容 (v-slot:) 替换为字符 #
1 | <div> |
渲染作用域
在 Vue 中有渲染作用域的概念:
- 父级模板里的所有内容都是在父级作用域中编译的
- 子模板里的所有内容都是在子作用域中编译的
作用域插槽
有时候我们希望插槽可以访问到子组件中的内容是非常重要的:
当一个组件被用来渲染一个数组元素时,我们使用插槽,并且希望插槽中没有显示每项的内容
这个 Vue 给我们提供了作用域插槽
来看下面的一个案例:
1.在 App.vue 中定义好数据
2.传递给 ShowNames 组件中
3.ShowNames 组件中遍历 names 数据
4.定义插槽的 prop
5.通过 v-slot:default 的方式获取到 slot 的 props
6.使用 slotProps 中的 item 和 index
App.vue
1 | <template> |
ShowNames.vue
1 | <template> |
注意:slotProps 不是固定的,可以自己更改
独占默认插槽
如果插槽是默认插槽 default,那么在使用的时候 v-slot:default=”slotProps”可以简写为 v-slot=”slotProps”:
并且如果插槽只有默认插槽时,组件的标签可以被当做插槽的模板来使用,这样,我们就可以将 v-slot 直接用在组件上
1 | <slot-names :names="names" v-slot="slotProps"> |
但是,如果有默认插槽和具名插槽,那么按照完整的 template 来编写
只要出现多个插槽,请始终为所有的插槽使用完整的基于