- 10.2 具有后备内容的插槽
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的过程,这个过程同样会进行子作用域的模板编译,因此两部分内容是相对独立的。
