一、前言
先贴一下源码 怎么处理scopedSlots的
if (currentParent && !element.forbidden) {
if (element.elseif || element.else) {
processIfConditions(element, currentParent)
} else {
if (element.slotScope) {
// scoped slot
// keep it in the children list so that v-else(-if) conditions can
// find it as the prev node.
const name = element.slotTarget || '"default"'
;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element
}
currentParent.children.push(element)
element.parent = currentParent
}
}
二、分析
在把template内容转为ast的过程当中,借用了数据算法中的堆栈技巧,将一个个vue dom解析为ast对象,从父到子插入到栈中,再重新构造一个ast树,在这个过程中,就对scopeSlot做了值的引用绑定。
三、解决问题
我们在项目中,做了封装search form和table list两个组件的封装,也就是search table这样一个集成了2个组件的通用组件,在这里使用了scope-slot插槽,某些页面是不需要更小的插槽组件传到子组件的,所以需要判断slot插槽下是否真实有内容存在。
开始使用了vm.slots只支持有具名插槽,但是对于将子组件属性在父级的插槽内容中暴露来使用的这种情况下,是无法作为判断依据的,所以不能使用这种判断方式,网上很多相关的解释也是有问题的。
所以在这里使用this.$scopedSlots来判断是最好的,根据源码,因为这个值是解析template时候就已经给它定义好了,如果声明了插槽但是没有给予实际内容,则为undefined。
四、附言
vm.slots: 无响应性。用来访问被插槽分发的内容。具名插槽根据其下property来访问,默认default property为所有所有没有被包含在具名插槽中的节点,或v-slot:default的内容。
vm.$scopedSlots: 用来访问作用域插槽。对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。(对于插槽的复杂使用来说,给到的信息更加具体)
- vue 2.1.0 新增了 vm.$scopedSlots。
- 作用域插槽函数现在保证返回一个 VNode 数组,除非在返回值无效的情况下返回 undefined。
- 所有的slots现在都会暴露在scopedSlots中。如果你在使用渲染函数,不论当前插槽是否带有作用域,我们都推荐始终通过$scopedSlots访问它们。