目录导航
这一节我们要分析的示例如下
我们在init的过程中,曾经看到过这样一句注释代码,即表示该if...else逻辑执行的就是一些配置的合并
通过之前的分析,我们知道在update过程中,当存在子元素为component时会执行子组件的init过程,此时的options._isComponent为true,执行initInternalComponent函数执行组件的配置合并,那么理所当然的,在else逻辑下便是我们new vue时的一些配置合并内容;由于js是单线程顺序执行的,又由于在new vue之前还调用了Vue.mixin方法
首先执行Vue.mixin,传递自定义的create函数,调用mergeOptions
a-进入接收参数为parent、child、vm
--parent:取自vue.options,我们知道此时还未new vue,因此该option为import vue时向vue挂载,查找import vue过程找到initGlobalAPI函数并定位到options初始化处
首先向vue上挂载了options属性,接着遍历ASSET_TYPES,而ASSET_TYPES指向
因此,initGlobalAPI后的vue.options上至少有以下属性,即parent的值
{
components:{},
directives:{},
filters:{},
_base:{}
}
--child:即vue.mixin传递的对象,值为created函数
--vm:undefined
回到mergeOptions,执行options合并
a-遍历parent,执行mergeField,选取合并策略
如果strats[key]不存在则使用默认合并策略
starts则来源于
我们当前存在components,则starts.components的合并策略为mergeAssets
由于我们此次合并child只有create,因此着重关心create合并,故直接看child遍历过程
对于parent没有的值,直接合并到option上,由于child只有一个created函数,因此直接合并
其合并策略为
来源为
对应的值为
因此合并之后的返回结果为
因此完成合并后的option如下,vue.mixin合并配置结束
{
components:{},
directives:{},
filters:{},
_base:{},
created:[created(){}]
}
执行new vue,进入init
首先进入else逻辑
调用resolveConstructorOptions函数,并将vue传入
a-Ctor.super;由于vue是根,因此为undefined,因此该组件直接返回option,换句话说,未执行合并,而是将我们之前合并mixin得到的option原封不动的返回
回到init函数,执行mergeOptions函数,此时传入的参数为
(‘mixin与import时合并的option’,‘new vue传入的option’,vue)
合并代码同样为
由于我们在new vue的时候只传递了render、el和created,因此只需要关心这几个值即可
当child的key=='created'时,调用mergeField并将key值传递;同样的从strats中匹配合并策略,找到合适的合并策略(mergeHook)并调用,此时的parentVal是vue.mixin混入的created,childVal为undefined
三元运算的结果为
所以res的伪代码为:[created(){},created(){}]
对于parent上本身没有的,则直接挂载到options上,因此,new vue后的options为
{
components:{},
directives:{},
filters:{},
_base:{} ,
created:[created(){},created(){}] ,
render:function(){},
el:"#app"
}
在之前的分析中我们知道,当render函数接受的是一个组件对象时,当vue执行render的过程中会调用createComponent方法,该方法将调用vue.extend去构建组件并继承vue的能力
当构建组件的options时,再一次调用了mergeOptions,此时传入的是组件options和vue的options,由于render已被执行,且created已被执行,el被使用(代码在执行的过程中一个组件始终保持一个options,用前push,用后delete),故vue的option如下
{
components:{},
directives:{},
filters:{},
_base:{} ,
created:[created(){}]
}
组件的options如下
根据之前vue.mixin和new vue的配置合并逻辑,我们知道合并的一个原则就是子组件多的添加上,同名的push进入,因此合并后的如下
{
components:{},
directives:{},
filters:{},
_base:{} ,
created:[created(){},created(){}],
mounted:[created(){}],
_Ctor:{},
template:""
}
这将作为子组件构建后的初始配置项,当执行vue的update过程中,由于我们这里是组件对象,将执行createComponent方法,并执行组件的init,因此将执行
之前我们分析过,这里的核心代码其实就是建立了引用关系并将组件的一些其他属性进行了赋值