Vue.js 的配置合并主要有两种场景,一种是我们直接调用Vue.js的Vue.extend,Vue.component,Vue.mixin
等钩子时, 另一种是使用new Vue实例化一个Vue 实例或者一个Vue 组件实例时,这里对两种情况做一些分析。
调用Vue.mixin/Vue.extend 时
Vue.mixin/Vue.extend 都是Vue 内部提供的一些全局API,通过这些全局钩子我们可以对Vue.js 配置做一写全局的混入。 在这里举一个具体实例
1 | <div id="app"></div> |
我们先调用了Vue.mixin
函数对Vue.js
配置做一个混入,然后成功实例化了一个Vue.js
实例。执行结果如下
我们对Vue.mixin
实现进行分析,Vue.mixin
的实现在src/core/global-api/mixin.js
中,Vue.mixin
的实现就是将this.options
与传入的对象mixinOption
做了一层mergeOptions。即this.options = mergeOptions(this.options,mixin)
。所以Vue.js
配置合并的核心即为函数mergerOptions
1 | import { mergeOptions } from '../util/index' |
实例化一个Vue实例时
同样的,当我们实例化一个Vue/VueComponent
,我们同样做同样需要做一些配置合并的工作
1 | if (options && options._isComponent) { |
当Vue
实例是一个组件实例时,会走向if
的逻辑,如果是一个Vue
实例时,会走向else
的逻辑
先看看else
的逻辑,同样举一个具体实例加以说明
1 | </head> |
首先执行Vue.extend
创造了一个VueComponent
,Vue.extend
的实现在src/core/global-api/extend.js
1 | Vue.extend = function (extendOptions: Object): Function { |
Vue.extend
的逻辑也很清晰,创造一个新的构造函数Sub
,利用Sub.prototype = Object.create(Super.prototype)
使Sub
继承Super
的属性,然后使用this.options = mergeOptions(Super.options,extendOption)
利用一定的规则将Super.options
与extendOptions
混合。最后返回一个VueComponent
的构造函数,在例子中,当代码实例化<user name="yyx"></user>
组件会调用他的构造函数最终走到
1 | vm.$options = mergeOptions( |
mergeOptions 的简单分析
上面我们分析了几种情况,发现代码最后都走向了mergeOptions
,我们来简单分析一下mergeOptions
的实现
mergeOptions
的实现在src/core/util/option.js
处
1 | export function mergeOptions ( |
mergeOption
的核心逻辑如上,对parent
与child
上的每一个key
调用mergeField
函数,Vue.js
对不同的属性有不同merge strats
。
componets 的合并策略
Vue.js
对components
的合并策略如下
1 | function mergeAssets ( |
逻辑也很简单,将parentVal
的属性放在res
的原型上,再将res
与childVal
做一层合并
LIFECYCLE_HOOKS(生命周期钩子)的合并策略
1 | function mergeHook ( |
实例化Vue 组件的合并策略
最后没有分析到的是组件实例的合并策略,即
1 | if (options && options._isComponent) { |
在何种情况options._isComponent
为 true
呢,
1 | export function createComponentInstanceForVnode ( |
此时options._isComponent
为true
走if
逻辑
1 | const opts = vm.$options = Object.create(vm.constructor.options) |
逻辑其实也很简单,首先继承构造器的属性,虽然将一些VueComponent
上的属性挂载在实例的$options
上