选项 el、propsData 的合并策略
接下来看看选项合并有哪些策略
/** * Options with restrictions */ 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) } }
在非生产环境下在 strats
策略对象上添加两个策略分别是 el
和 propsData,两个属性值都是函数
这两个策略函数是用来合并 el
选项和 propsData
选项的。
if (!vm) { warn( `option "${key}" can only be used during instance ` + 'creation with the `new` keyword.' ) }
if判断是否有传递vm,如果没有就会警告,提示你 el
选项或者 propsData
选项只能在使用 new
操作符创建实例的时候可用
如果没有vm,则说明是子组件选项?为什么这样说?
首先我们要搞清楚策略函数中的 vm
参数是哪里来的:看看vue源码中的mergeField
函数
function mergeField (key) { var strat = strats[key] || defaultStrat; options[key] = strat(parent[key], child[key], vm, key); }
第三个参数vm就是我们策略中使用的vm,
在看看_init
方法:
// _init 方法中调用 mergeOptions 函数,第三个参数是 Vue 实例 vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm )
通过_init方法可以看出,策略函数中的 vm
来自于 mergeOptions
函数的第三个参数,
mergeOptions函数传第三个参数,策略中就拿不到vm参数,除了_init方法中调用了mergeOptions函数,其他很多地方都调用了
Vue.extend方法中也调用了mergeoptions函数
Sub.options = mergeOptions( Super.options, extendOptions )
此时在Vue.extend方法中调用了mergeOptions函数,但是没有传第三个参数vm,所以在策略中无法拿到vm,
就能得出mergeOptions函数是在实例化时使用new操作符走_init方法还是继承时走的Vue.extend方法
子组件是通过实例化子类完成的,子类是通过Vue.extend方法创造出来的,
综上得出可以通过if(!vm)判断是否是子组件
接下来回到开头:
return defaultStrat(parent, child)
调用了defaultStrat方法传入两个参数分别是父选项和子选项。
defaultStrat方法有什么作用呢?就像它的名字一样,默认的策略,或许你还不太懂,我们来看看defaultStrat方法吧
const defaultStrat = function (parentVal: any, childVal: any): any {
return childVal === undefined
? parentVal
: childVal //只要子选项不是 undefined
那么就是用子选项,否则使用父选项。
}
strats.el
和 strats.propsData
这两个策略函数是只有在非生产环境才有的,在生产环境下访问这两个函数将会得到 undefined
,那这个时候 mergeField
函数的第一句代码就起作用了:
// 当一个选项没有对应的策略函数时,使用默认策略 const strat = strats[key] || defaultStrat
所以在生产环境将直接使用默认的策略函数 defaultStrat
来处理 el
和 propsData
这两个选项
//上班划水写博客,下班时间到了 溜了溜了。。。
//下次更新 选项data合并策略