选项 data 的合并策略
我们跳过mergeData
以及 mergeDataOrFn
,我们暂且不关注这两个函数的作用。暂且跳过继续看下面的代码:
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) }
在strats策略对象上面添加了一个data策略函数,进行选项data的策略合并
if (!vm) {}如同上一篇文章介绍一样 用来判断是否是子组件选项,
如果是子组件选项 return mergeDataOrFn(parentVal, childVal)
如果不是 return mergeDataOrFn(parentVal, childVal, vm)
再来看看if判断里面的内容:
if (childVal && typeof childVal !== 'function') {}
判断是否又子组件的data,并且检测是否是一个function,如果不是函数则会警告,并且返回parentVal
如果childval是函数 则会返回mergeDataOrFn(parentVal, childVal) 执行结果
后面就不用说了, 如果又vm 就执行mergeDataOrFn(parentVal, childVal, vm)
接下来我们看看一直调用的mergeDataOrFn函数是什么:
/** * Data */ export function mergeDataOrFn ( parentVal: any, childVal: any, vm?: Component ): ?Function { if (!vm) { // in a Vue.extend merge, both should be functions if (!childVal) { return parentVal } if (!parentVal) { return childVal } // when parentVal & childVal are both present, // we need to return a function that returns the // merged result of both functions... no need to // check if parentVal is a function here because // it has to be a function to pass previous merges. return function mergedDataFn () { return mergeData( typeof childVal === 'function' ? childVal.call(this, this) : childVal, typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal ) } } else { return function mergedInstanceDataFn () { // instance merge const instanceData = typeof childVal === 'function' ? childVal.call(vm, vm) : childVal const defaultData = typeof parentVal === 'function' ? parentVal.call(vm, vm) : parentVal if (instanceData) { return mergeData(instanceData, defaultData) } else { return defaultData } } } }
整体的也是和之前的几个函数一样 首先对vm的判断,其中就mergeData函数需要介绍下,看下mergeData源码,这个函数是用来干嘛的
/** * Helper that recursively merges two data objects together. */ function mergeData (to: Object, from: ?Object): Object { // 没有 from 直接返回 to if (!from) return to let key, toVal, fromVal const keys = Object.keys(from) // 遍历 from 的 key for (let i = 0; i < keys.length; i++) { key = keys[i] toVal = to[key] fromVal = from[key] // 如果 from 对象中的 key 不在 to 对象中,则使用 set 函数为 to 对象设置 key 及相应的值 if (!hasOwn(to, key)) { set(to, key, fromVal) // 如果 from 对象中的 key 也在 to 对象中,且这两个属性的值都是纯对象则递归进行深度合并 } else if (isPlainObject(toVal) && isPlainObject(fromVal)) { mergeData(toVal, fromVal) } // 其他情况什么都不做 } return to }
接收两个参数,to,from;
根据调用传参 to
对应的是 childVal
产生的纯对象,from
对应 parentVal
产生的纯对象
这个函数作用就是:将 from
对象的属性混合到 to
对象中,也可以说是将 parentVal
对象的属性混合到 childVal
中,最后返回的是处理后的 childVal
对象。
合并阶段 strats.data
将被处理成一个函数,但是这个函数并没有被执行,而是到了后面初始化的阶段才执行的,
重点:!!!!!!!!!!!
mergeData
函数只有在初始化的时候才会执行,进行数据合并;
Vue
的初始化的时候, inject
和 props
这两个选项的初始化是先于 data
选项的,这就保证了我们能够使用 props
初始化 data
中的数据