vue中的混入,可以在一定程度上提高代码的复用性。通俗来说,混入类似于“继承”,当前组件对象继承于组件对象,一般情况下遵循“就近原则”。但是与继承不同的是,继承一般都跟随者属性的重写与合并,混入在不同的配置项中,有着不同的混入策略,下面会一一进行介绍vue不同配置项的混入策略。vue混入的基本流程如图所示,混入属性的合并是发生在组件的生命周期钩子调用之前的。
vue中,混入实现的主要代码如下:
1 export function mergeOptions ( 2 parent: Object, 3 child: Object, 4 vm?: Component 5 ): Object { 6 if (process.env.NODE_ENV !== 'production') { 7 // 检测组件名称是否合法 8 checkComponents(child) 9 } 10 11 if (typeof child === 'function') { 12 child = child.options 13 } 14 // 格式化属性名称 15 normalizeProps(child, vm) 16 // 格式化依赖注入内容 17 normalizeInject(child, vm) 18 // 格式化指令内容 19 normalizeDirectives(child) 20 21 // Apply extends and mixins on the child options, 22 // but only if it is a raw options object that isn't 23 // the result of another mergeOptions call. 24 // Only merged options has the _base property. 25 // 只有合并的options拥有_base属性 26 // 需要递归进行合并属性 27 // 首先合并extends和mixins 28 if (!child._base) { 29 if (child.extends) { 30 parent = mergeOptions(parent, child.extends, vm) 31 } 32 if (child.mixins) { 33 for (let i = 0, l = child.mixins.length; i < l; i++) { 34 parent = mergeOptions(parent, child.mixins[i], vm) 35 } 36 } 37 } 38 39 const options = {} 40 let key 41 for (key in parent) { 42 mergeField(key) 43 } 44 for (key in child) { 45 if (!hasOwn(parent, key)) { 46 mergeField(key) 47 } 48 } 49 // 合并属性 50 function mergeField (key) { 51 // 获取属性的合并策略 52 const strat = strats[key] || defaultStrat 53 // 调用属性合并策略,返回值为属性合并结果 54 options[key] = strat(parent[key], child[key], vm, key) 55 } 56 return options 57 }
具体某个字段的合并,调用的是mergeField方法,此方法主要是获取代码混入策略,返回值作为混入的结果。通过调试我们可以看出,混入的策略对象中包含我们常见的vue属性,如下所示:
混入的实现,采用了策略模式的设计模式,在对组件数据初始化时,会遍历组件的配置文件,根据配置文件,调用对应的策略方法。如果组件中存在不是vue指定的配置,就是策略类strats中不包含的属性,就会调用默认的合并方法defaultStrat,该方法的定义如下:
/** * Default strategy. * 默认的属性合并策略,采用就近原则,如果子级没有,就采用父级的 */ const defaultStrat = function (parentVal: any, childVal: any): any { return childVal === undefined ? parentVal : childVal }
strats是从哪来的呢? strats读取的是用户自定义配置。在项目初始化时,会初始化所有的属性合并策略,如下图所示:
未完待续。。。。。。