vue源码分析-3-全局api

439 阅读2分钟

initGlobalAPI(Vue)

全局api是在src/core/index.js中引入并执行的

Vue.util下定义了四个方法

warn是提示警告用的,非重点

extend方法是合并扩展对象属性,实现很简单

mergeOptions方法是合并options

defineReactive方法是定义响应式对象的,将在响应式原理章节讲解

Vue.util = {
    // 提示警告
    warn,
    // 合并扩展对象属性
    extend,
    // 合并两个options的方法
    mergeOptions,
    // 定义响应式属性的方法
    defineReactive
  }

接下来又定义了Vue构造函数的三个静态方法 这三个方法的主要作用都是为了实现响应式原理,这些方法将在响应式原理章节讲解

  // 静态 set方法
  Vue.set = set
  // 静态 delete方法
  Vue.delete = del
  // 静态 nexttick方法
  Vue.nextTick = nextTick
  
  Vue.observable = xxx

接下来定义了一些Vue.options上的属性

initUse(Vue)与插件机制相关,具体见Vue.use()插件机制章节

// 初始化Vue的options属性(静态属性)
  Vue.options = Object.create(null)
  // 初始化'components','directives','filters'  属性
  ASSET_TYPES.forEach(type => {
    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.
  // _base标识Vue是所有组件的基础构造函数
  Vue.options._base = Vue

  // 初始化components属性,KeepAlive组件
  extend(Vue.options.components, builtInComponents)

  // 定义Vue.use插件方法
  initUse(Vue)
  // 定义Vue.minx方法
  initMixin(Vue)
  // 定义Vue.extend方法
  initExtend(Vue)
  // 定义Vue.component  Vue.directive  Vue.filter方法
  initAssetRegisters(Vue)

initMixin方法主要定义了Vue.mixin方法,此方法的作用就是可以合并向Vue.options混入属性,也就是属性合并

initMixin (Vue: GlobalAPI) {
  Vue.mixin = function (mixin: Object) {
    this.options = mergeOptions(this.options, mixin)
    return this
  }

initExtend() 方法主要是定义了Vue.extend方法,调用此方法可以继承Vue构造函数生成一个Sub子构造函数

initExtend (Vue: GlobalAPI) {
  /**
   * Each instance constructor, including Vue, has a unique
   * cid. This enables us to create wrapped "child
   * constructors" for prototypal inheritance and cache them.
   */
  Vue.cid = 0
  let cid = 1

  /**
   * Class inheritance
   *  基于Vue构建一个新的Vue对象
   */
  Vue.extend = function (extendOptions: Object): Function {
    // 待合并扩展的options
    extendOptions = extendOptions || {}
    // 保存自身实例
    const Super = this
    // 取得自身实例的cid
    const SuperId = Super.cid
    // 做了一波缓存操作,如果同一待扩展对象多次用调用同一个Vue实例的extend方法,
    // 那么直接从_Ctor中获取
    const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
    if (cachedCtors[SuperId]) {
      return cachedCtors[SuperId]
    }

    // 做了一波名称合法校验
    const name = extendOptions.name || Super.options.name
    if (process.env.NODE_ENV !== 'production' && name) {
      validateComponentName(name)
    }

    // 定义子构造器,以下操作实现了一波原型继承
    const Sub = function VueComponent (options) {
      // 子构造器调用父类构造方法
      this._init(options)
    }
    // 给子类原型赋值,这里有个问题就是constructor还是指向Super啊
    Sub.prototype = Object.create(Super.prototype)
    // 所以这里给重新指向了一波constructor
    Sub.prototype.constructor = Sub
    // cid++
    Sub.cid = cid++
    // 合并options
    Sub.options = mergeOptions(
      Super.options,
      extendOptions
    )
    // 子类的super属性指向父类
    Sub['super'] = Super

    // For props and computed properties, we define the proxy getters on
    // the Vue instances at extension time, on the extended prototype. This
    // avoids Object.defineProperty calls for each instance created.
    if (Sub.options.props) {
      initProps(Sub)
    }
    if (Sub.options.computed) {
      initComputed(Sub)
    }

    // allow further extension/mixin/plugin usage
    Sub.extend = Super.extend
    Sub.mixin = Super.mixin
    Sub.use = Super.use

    // create asset registers, so extended classes
    // can have their private assets too.
    ASSET_TYPES.forEach(function (type) {
      Sub[type] = Super[type]
    })
    // enable recursive self-lookup
    if (name) {
      Sub.options.components[name] = Sub
    }

    // keep a reference to the super options at extension time.
    // later at instantiation we can check if Super's options have
    // been updated.
    Sub.superOptions = Super.options
    Sub.extendOptions = extendOptions
    Sub.sealedOptions = extend({}, Sub.options)

    // 缓存
    // cache constructor
    cachedCtors[SuperId] = Sub
    return Sub
  }
}