美文网首页Vue从入门到精通
vue源码阅读——合并options

vue源码阅读——合并options

作者: 丨ouo丨 | 来源:发表于2017-11-16 22:43 被阅读3466次

    vue里面,我们是可以自己传一些数据进去的。比如说

    var vm = new Vue({
          el: '#app',
          data: {
            message: 'Hello Vue!'
          }
    })
    

    像这种的话,我们在new Vue的时候传了一个对象。就是

    {
          el: '#app',
          data: {
            message: 'Hello Vue!'
          }
    }
    

    那么其实我们新建的这个Vue实例,会在代码运行后增加很多新的东西进去。我们把我们传入的这个对象叫options,这篇博客主要讲的就是关于vm.$options这个属性,这个属性在vue整个框架中都是不断出现的。所以弄清楚vm.$options对于源码阅读也十分有裨益。

    先上一个随心所欲的图



    下面一步步讲~
    首先我们要找vm.$options最开始是在哪里出现的。在initMixin这个函数里面最早出现vm.$options的定义。

    vm.$options = mergeOptions(
            resolveConstructorOptions(vm.constructor),
            options || {},
            vm
    )
    

    我们结合图看,mergeOptions主要分成两块,就是resolveConstructorOptions(vm.constructor)optionsmergeOptions这个函数的功能就是要把这两个合在一起。
    options是我们自己写代码的时候传进去的,
    因此需要看看的就是resolveConstructorOptions这一块。resolveConstructorOptions这个函数主要就是返回构造函数里面的options。

    1. resolveConstructorOptions
    export function resolveConstructorOptions (Ctor: Class<Component>) {
      let options = Ctor.options
      if (Ctor.super) {
        const superOptions = resolveConstructorOptions(Ctor.super)
        const cachedSuperOptions = Ctor.superOptions
        if (superOptions !== cachedSuperOptions) {
          // super option changed,
          // need to resolve new options.
          Ctor.superOptions = superOptions
          // check if there are any late-modified/attached options (#4976)
          const modifiedOptions = resolveModifiedOptions(Ctor)
          // update base extend options
          if (modifiedOptions) {
            extend(Ctor.extendOptions, modifiedOptions)
          }
          options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
          if (options.name) {
            options.components[options.name] = Ctor
          }
        }
      }
      return options
    }
    

    这里对应一下前面的图,就是把本身的options和父类的options合起来。

    1. mergeOptions
    export function mergeOptions (
      parent: Object,
      child: Object,
      vm?: Component
    ): Object {
      if (process.env.NODE_ENV !== 'production') {
        checkComponents(child)
      }
    
      if (typeof child === 'function') {
        child = child.options
      }
    
      normalizeProps(child, vm)
      normalizeInject(child, vm)
      normalizeDirectives(child)
      const extendsFrom = child.extends
      if (extendsFrom) {
        parent = mergeOptions(parent, extendsFrom, vm)
      }
      if (child.mixins) {
        for (let i = 0, l = child.mixins.length; i < l; i++) {
          parent = mergeOptions(parent, child.mixins[i], vm)
        }
      }
      const options = {}
      let key
      for (key in parent) { // 遍历Vue.options对象的属性
        mergeField(key)
      }
      for (key in child) { // 遍历options对象的属性
        if (!hasOwn(parent, key)) {
          mergeField(key)
        }
      }
      function mergeField (key) { // 每个key都会对应在strats中初始化好的函数
        const strat = strats[key] || defaultStrat
        options[key] = strat(parent[key], child[key], vm, key)
      }
      return options
    }
    
    1. vm.constructor里面主要有哪些options:components,directives,filters,还有一个_base用来指向构造函数自身。initGlobalAPI这个函数中有许多初始化构造函数的代码,给构造函数添加options就在其中。可以看看初始化的代码:
    function initGlobalAPI (Vue) {
      // config
      var configDef = {};
      configDef.get = function () { return config; };
      if (process.env.NODE_ENV !== 'production') {
        configDef.set = function () {
          warn(
            'Do not replace the Vue.config object, set individual fields instead.'
          );
        };
      }
      Object.defineProperty(Vue, 'config', configDef);
    
      // exposed util methods.
      // NOTE: these are not considered part of the public API - avoid relying on
      // them unless you are aware of the risk.
      Vue.util = {
        warn: warn,
        extend: extend,
        mergeOptions: mergeOptions,
        defineReactive: defineReactive
      };
    
      Vue.set = set;
      Vue.delete = del;
      Vue.nextTick = nextTick;
    
      Vue.options = Object.create(null);  // 这里开始
      ASSET_TYPES.forEach(function (type) { // 添加components,directives,filters
        Vue.options[type + 's'] = Object.create(null);
      });
    
      // this is used to identify the "base" constructor to extend all plain-object
      // components with in Weex's multi-instance scenarios.
      Vue.options._base = Vue; // 指向Vue本身的 _base 
    
      extend(Vue.options.components, builtInComponents); // 把builtInComponents里面的属性添加到Vue.options.components里面
    
      initUse(Vue);
      initMixin$1(Vue);
      initExtend(Vue);
      initAssetRegisters(Vue);
    }
    

    相关文章

      网友评论

        本文标题:vue源码阅读——合并options

        本文链接:https://www.haomeiwen.com/subject/vairvxtx.html