10.2 具有后备内容的插槽
有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。查看源码发现后备内容插槽的逻辑也很好理解。
var child = {
template: `<div class="child"><slot>后备内容</slot></div>`
}
var vm = new Vue({
el: '#app',
components: {
child
},
template: `<div id="app"><child></child></div>`
})
// 父没有插槽内容,子的slot会渲染后备内容
<div class="child">后备内容</div>
父组件没有需要分发的内容,子组件会默认显示插槽里面的内容。源码中的不同体现在下面的几点。
- 父组件渲染过程由于没有需要分发的子节点,所以不再需要拥有
componentOptions.children
属性来记录内容。 - 因此子组件也拿不到
$slot
属性的内容. - 子组件的
render
函数最后在_t
函数参数会携带第二个参数,该参数以数组的形式传入slot
插槽的后备内容。例with(this){return _c('div',{staticClass:"child"},[_t("default",[_v("test")])],2)}
- 渲染子
Vnode
会执行renderSlot(即:_t)
函数时,第二个参数fallback
有值,且this.$slots
没值,vnode
会直接返回后备内容作为渲染对象。
function renderSlot (
name,
fallback, // slot插槽后备内容(针对后备内容)
props, // 子传给父的值(作用域插槽)
bindObject
){
if() {
···
}else{
//fallback为后备内容
// 如果父占位符组件没有插槽内容,this.$slots不会有值,此时vnode节点为后备内容节点。
nodes = this.$slots[name] || fallback;
}
}
最终,在父组件没有提供内容时,slot
的后备内容被渲染。
有了这些基础,我们再来看官网给的一条规则。
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
父组件模板的内容在父组件编译阶段就确定了,并且保存在componentOptions
属性中,而子组件有自身初始化init
的过程,这个过程同样会进行子作用域的模板编译,因此两部分内容是相对独立的。