new Vue(options)
中首先处理的是下面一段代码, 这次就剖析这一段代码;
|
|
初始化vm.$option
上面代码主要目的就是初始化vm.$option. 其中逻辑很简单,如果传入的option是一个组件,执行initInternalComponent, 否则执行mergeOptions;
initInternalComponent
initInternalComponent非常简单,就是以Vue.options为原型创建vm.$options, 并把options中的属性复制到vm.$options;
|
|
mergeOptions
mergeOptions接受三个参数,这个方法比较复杂; 首先接受三个参数
[parent, child, vm] = [resolveConstructorOptions(vm.constructor), options || {}, vm]
其中parent为resolveConstructorOptions(vm.constructor), 得到结果为Vue.options;child跟vm没什么说的;我们来看看mergeOptions做了什么;
具体代码在github这里; 主要逻辑是:
|
|
其中normalizeProps/normalizeInject/normalizeDirectives主要是格式化对象;
normalizeProps主要是把options中的props格式化为如下对象 :
|
|
normalizeProps主要是把options中的inject格式化为如下对象:
normalizeDirectives主要是把options中的directives格式化为如下对象:
|
|
extend与mixins
接下来的代码其实是vue的混合用法,这里有官方文档-混合描述;
由于mixins与extend用法一致,只对mixins讲述:
|
|
上面代码其实是递归调用mergeOptions, 并把mixins的内容递归处理到parent对象中;
接着初始化一个空对象{}这里我们记做obj, 并遍历parent里的key,mergeField到options中;
|
|
mergeField是一个多态函数,根据传递的key值不同,parent与child合并的方式不同:
- 如果key是
el
或者propsData
时:obj[key] = child[key] === undefined ? parent[key] : child[key]
- 如果key是
data
, 则递归的一层一层把所有的parent不存在的数据复制到child 如果key是vue实例的生命周期, 则
obj[key] = parent[key].concat(child[key])
beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed, activated, deactivated
如果key是
components, directives, filters
这些key值,则12const res = Object.create(parent[ke] || null)return child[key] ? extend(res, child[ke]) : res如果key是watch,与生命周期类似
- 如果key是
prosp/methods/inject/computed
时,与componets类似;
也即:
- key值为生命周期或者watch时,同名钩子函数将混合为一个数组,因此都将被调用。另外,混合对象的钩子将在组件自身钩子之前调用.
- 当为
prosp/methods/inject/computed/components/directives/filters
时,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。
如下面一个例子:
|
|
总结
上面的所有步骤就是初始化传入的options中的一些对象, 并把混合的mixins和extend合并起来,最后赋值给vue实例的$options.