以下例子是在 Vue@2.6.2 中运行的。
vm.$slots 与 vm.$scopedSlots 是两个与插槽相关的属性。在使用渲染函数替代 vue 的模板功能时我们可能需要用到这两个属性来实现插槽的功能。
下面利用一个例子来研究 vm.$slots vm.$scopedSlots 的区别。
1 | <!-- App.vue --> |
1 | <!-- HelloWorld.vue --> |
我们在 HelloWorld.vue 内定义三个具名插槽和一个默认插槽。在 App.vue 内实例化 HelloWorld 组件时,只使用了 head default foot 插槽,其中 head 插槽是一个作用域插槽。
然后我们将 vm.$slots vm.$scopedSlots打印的到控制台上,chrome 浏览器上打印的结果如下:
vm.\$slots
观察发现
- 只有被使用到的插槽才会出现在
vm.$slots内。 - 默认插槽和具名插槽的值是虚拟 dom 数组(
VNode[]),作用域插槽对应的值是一个get方法且属性修饰为不可枚举。
vm.\$scopedSlots
观察发现
- 只有被使用到的插槽才会出现在
vm.$scopedSlots内。 - 这里面多了
$stable_normalized属性。具体什么作用,未知。 - 无论是具名插槽、默认插槽、作用域插槽都在,而且值是一个工厂函数,调用后会返回虚拟 dom 数组(
VNode[])。 - 作用域插槽对应的函数内多个参数
scope,可以通过它将参数传给插槽。 - 所有值都是可枚举的。
vm.\$slots 在开发中的使用
以下例子来自 Vue 官方文档,仅做了些许的改动。
简单的例子
1 | <!-- MyHeadline.vue --> |
1 | <!-- App.vue --> |
页面渲染的结果:
页面的 html 结构:
MyHeadline 组件的目的很明显,就是根据传入的 level 属性生成对应级别的 h 标签。使用 vue 的模板是很难实现这样的功能的,所以这里用到了 vue 的渲染函数(其实 vue 模板最终也是编译成渲染函数)。
进阶例子
1 | <!-- AnchoredHeading.vue --> |
1 | <!-- App.vue --> |
页面渲染结果:
页面 html 结构:
vm.\$scopedSlots 在开发中的使用
简单例子
1 | <!-- Menu.vue --> |
1 | <!-- MenuItem.vue --> |
1 | <!-- App.vue --> |
在Menu.vue内我们通过this.$scopedSlots.default({ title: "🌎 菜单栏目 🌎" })向作用域插槽传了参数({ title: "🌎 菜单栏目 🌎" })。然后我们在 App.vue 内使用 <template slot-scope="{title}"> 获得传过来的参数(这里用了解构赋值)。
上面只是为了展示vm.$scopedSlots在渲染函数内的使用,这个例子内的行为有点多此一举。
页面渲染结果:
页面 html 结构:
在渲染函数内插入作用域插槽
如果我们把上面那个例子里App.vue的模板写法改成渲染函数的话,我们该如何插入作用域插槽呢?
在模板写法内插入插槽很简单,只要在组件标签内插入即可。在渲染函数内需要用到createElement方法内的scopedSlots选项。
1 | <!-- App.vue --> |
这个写法和上面的模板写法的效果是等同的。