Vue源码学习系列04——Vue构造函数解析(二): 选项合并策略(optionMergeStrategies)

打个小广告哈,最近做了个小程序,来测测你的工作性价比吧~(微信扫码打开小程序即可)

工作性价比评估器


上一节可以看成是merge数据前期准备,下面就介绍到了我们的mergeOption的重头戏啦——merge。先看代码(仍然是mergeOptions里面的代码):

const options = {
   }
let key
for (key in parent) {
   
  mergeField(key)
}
for (key in child) {
   
  if (!hasOwn(parent, key)) {
   
    mergeField(key)
  }
}
function mergeField (key) {
   
  const strat = strats[key] || defaultStrat
  options[key] = strat(parent[key], child[key], vm, key)
}
return options

可以看到,首先定义了options,再给这个options赋值,最后返回options。这就是mergeOptions方法主要干的事。那么,我们知道,Vue提供的属性很多,比如:el, data, props, filters … 这些属性是怎么来merge的呢?是不是有什么合并的规则,每个属性有自己的对应合并规则呢?
是的。
这段代码有两个for循环,for循环内部都使用了mergeField函数。我们先来看看这个函数:

function mergeField (key) {
   
  const strat = strats[key] || defaultStrat
  options[key] = strat(parent[key], child[key], vm, key)
}

该函数接受了一个key作为参数,这个key就是属性名称。然后定义了一个strat变量,它的值是strats[key] || defaultStrat,也就是说,会在starts这个对象中找有没有这个key对应的值,有就用这个值,没有的话就用defaultStrat作为默认值。所以,这个strats可以看成我们上面说的合并规则集。它的定义就在当前文件中,我们一点一点来看。

合并策略
/**
 * Option overwriting strategies are functions that handle
 * how to merge a parent option value and a child option
 * value into the final value.
 * 
 * 选项重写策略是一堆函数, 它们负责把一个父选项和一个子选项合并成一个最终的值
 */
const strats = config.optionMergeStrategies

首先在上面定义了这个对象。它的值是config.optionMergeStrategies,顺着依赖找到这个定义可以发现他就是一个空对象: Object.create(null)。所以此时: strats = {}

el和propsData

然后开始给它添加规则了,先是这两个:

/**
 * Options with restrictions
 * 
 * el 和 propsData 的合并策略一样
 * 注意: 它们只能给使用 new 操作符 创建的 Vue 实例使用
 */
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)
  }
}

很简单,就是给 elpropsData 设置合并规则——默认的规则。慢着,我们先看一下这个默认合并策略是什么吧,毕竟出现两次了,这也是在当前文件中定义的:

/**
 * Default strategy.
 */
const defaultStrat = function (parentVal: any, childVal: any): any {
   
  return childVal === undefined
    ? parentVal
    : childVal
}

默认的策略很简单,就是有孩子用孩子,没孩子用爸爸。也就是无第二个参数时就使用第一个参数的值。
Ok,继续看

data

接下来是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)
}

首先的判断的 if(!vm), 还有内部的两个return,参数列表只少了个vm,那么有vm和没有vm有什么不一样吗?
首先,不一样是肯定的,现在你可以简单的理解为,没有vm的操作的是子组件

继续,如果没有提供vm的话,进入if分支,接着又是一个if:childVal && typeof childVal !== 'function',你可能不太了解这个判断,但是你肯定认识这段警告的内容:data选项要是一个函数。是不是很熟悉?
如果满足data是函数的话,则会执行:return 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
    // 在 Vue.extend 的合并中,两个都应该是函数
    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.
    // 当 parentVal 和 childVal 都存在的时候,我们需要返回一个函数,这个函数返回这两个对象
    // 合并的结果。这里不需要检查parentVal是不是函数,因为它只有是函数才可以通过之前的合并。
    return function mergedDataFn () {
   
      return mergeData(
        typeof childVal === 'function' ? childVal.call(this, this) : childVal,
        typeof
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值