1.5 合并策略

合并策略之所以是难点,其中一个是合并选项类型繁多,合并规则随着选项的不同也呈现差异。概括起来思路主要是以下两点:

  1. Vue针对每个规定的选项都有定义好的合并策略,例如data,component,mounted等。如果合并的子父配置都具有相同的选项,则只需要按照规定好的策略进行选项合并即可。
  2. 由于Vue传递的选项是开放式的,所有也存在传递的选项没有自定义选项的情况,这时候由于选项不存在默认的合并策略,所以处理的原则是有子类配置选项则默认使用子类配置选项,没有则选择父类配置选项。

我们通过这两个思想去分析源码的实现,先看看mergeOptions除了规范检测后的逻辑。

  1. function mergeOptions ( parent, child, vm ) {
  2. ···
  3. var options = {};
  4. var key;
  5. for (key in parent) {
  6. mergeField(key);
  7. }
  8. for (key in child) {
  9. if (!hasOwn(parent, key)) {
  10. mergeField(key);
  11. }
  12. }
  13. function mergeField (key) {
  14. // 如果有自定义选项策略,则使用自定义选项策略,否则选择使用默认策略。
  15. var strat = strats[key] || defaultStrat;
  16. options[key] = strat(parent[key], child[key], vm, key);
  17. }
  18. return options
  19. }

两个for循环规定了合并的顺序,以自定义选项策略优先,如果没有才会使用默认策略。而strats下每个key对应的便是每个特殊选项的合并策略

1.5.1 默认策略

我们可以用丰富的选项去定义实例的行为,大致可以分为以下几类:

  1. data,props,computed等选项定义实例数据
  2. mounted, created, destoryed等定义生命周期函数
  3. components注册组件
  4. methods选项定义实例方法

当然还有诸如watch,inject,directives,filter等选项,总而言之,Vue提供的配置项是丰富的。除此之外,我们也可以使用没有默认配置策略的选项,典型的例子是状态管理Vuex和配套路由vue-router的引入:

  1. new Vue({
  2. store, // vuex
  3. router// vue-router
  4. })

不管是插件也好,还是用户自定义的选项,他们的合并策略会遵循思路的第二点:子配置存在则取子配置,不存在则取父配置,即用子去覆盖父。。它的描述在defaultStrat中。

  1. // 用户自定义选项策略
  2. var defaultStrat = function (parentVal, childVal) {
  3. // 子不存在则用父,子存在则用子配置
  4. return childVal === undefined
  5. ? parentVal
  6. : childVal
  7. };

接下来会进入某些具体的合并策略的分析,大致分为五类:

1. 常规选项合并

2. 自带资源选项合并

3. 生命周期钩子合并

4. watch选项合并

5. props,methods, inject, computed类似选项合并