TODO:
export function mergeOptions (parent: Object,child: Object,vm?: Component): Object {// 校验组件命名是否规范if (process.env.NODE_ENV !== 'production') {checkComponents(child)}// 如果 child 是另外一个构造函数则取其静态属性来进行合并if (typeof child === 'function') {child = child.options}// 格式化 Props 格式// 最终形态为 {[p: string]: {type: Number | String | Boolean | Array | Object, default?: any }}normalizeProps(child, vm)// 格式化 inject// 最终形态为 inject: {[p: string]: {from: string, [p: string]: string}}normalizeInject(child, vm)// 格式化 directives// 最终形态为 directive: {bind?: Function, update?: Function}normalizeDirectives(child)// _base 的有无代表是否已经 merge 过if (!child._base) {// 如果是继承的实例/构造函数,则递归的向上合并所有 optionsif (child.extends) {parent = mergeOptions(parent, child.extends, vm)}// 若果有 mixins, 则遍历合并 mixins 中的 optionsif (child.mixins) {for (let i = 0, l = child.mixins.length; i < l; i++) {parent = mergeOptions(parent, child.mixins[i], vm)}}}// 到此为止,除了 child 的 options 没合并外,父类和 mixins 的 options 均已合并// 将 parent.options 和 child.options 中的交集通过 config.optionMergeStrategies 中的配置过的对应策略来合并,// 比如 web 端的 el、propsData 如果两边都有就会报错,因为只有可能根节点, 通过 new Vue 的才有可能有需要有 el、propsData 配置// 如果没有对应策略则优先取 child 的值// 接着再将 child 中 parent 没有的合并到 options 中const options = {}let keyfor (key in parent) {mergeField(key)}for (key in child) {if (!hasOwn(parent, key)) {mergeField(key)}}function mergeField (key) {const strat = strats[key] || defaultStrat// 此处可能会没有 vm,没有 vm 意味着当前合并的场景并非 Vue 实例化,反之则是。// 如果没有 vm,则一些特殊的合并策略则会得出不同的结果// 比如options[key] = strat(parent[key], child[key], vm, key)}return options}
el、propsData 的合并策略
if (process.env.NODE_ENV !== 'production') {strats.el = strats.propsData = function (parent, child, vm, key) {if (!vm) {warn(`option "${key}" can only be used during instance ` +'creation with the `new` keyword.')}return defaultStrat(parent, child)}}
由于 el、propsData 只有在 new Vue 的时候才会出现,所以如果没传了 vm 则意味着并非在 new Vue 的时候出现,则报错
data 的合并策略
strats.data = function (parentVal: any,childVal: any,vm?: Component): ?Function {if (!vm) {if (childVal && typeof childVal !== 'function') {process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' +'that returns a per-instance value in component ' +'definitions.',vm)return parentVal}return mergeDataOrFn(parentVal, childVal)}return mergeDataOrFn(parentVal, childVal, vm)}
如果不是在实例化过程中,传的 child.data 不是函数则报错并且只返回 parent.data,反之则合并。
合并的规则是,如果不是在实例化过程中合并,则返回一个函数,该函数调用后则会调用返回 child.data 为优先的
