[Vue源码解析】全局API的实现原理~

14 篇文章 0 订阅

[Vue源码解析] 全局API的实现原理

1、 Vue.extend(options)

用法:使用基础的Vue构造器创建一个子类,options为自定义组件选项

/**
 * Vue.extend(options)
 */

let cid = 1

Vue.extend = function (extendOptions) {
  extendOptions = extendOptions || {}
  const Super = this
  const SuperId = Super.cid
  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') {
    if (!/^[a-zA-Z][\w-]*$/.test(name)) {     //名称不符合规范时警告
      warn('')
    }
  }
  const Sub = function VueComponent (options) {
    this._init(options)
  }
  Sub.prototype = Object.create(Super.prototype)
  Sub.prototype.constructor = Sub
  Sub.cid = cid++

  Sub.options = mergeOptions(     //继承options属性,该函数将两个对象的options属性合并后返回新的options对象
    Super.options,
    extendOptions
  )

  Sub['super'] = Super

  if (Sub.options.props) {
    initProps(Sub)
  }

  if (Sub.options.computed) {
    initComputed(Sub)
  }

  Sub.extend = Super.extend
  Sub.mixin = Super.mixin
  Sub.use = Super.use

  //ASSET_TYPES = ['component', 'directive', 'filter']
  ASSET_TYPES.forEach(type => {
    Sub[type] = Super[type]
  });

  if (name) {
    Sub.options.components[name] = Sub
  }

  Sub.superOptions = Super.options
  Sub.extendOptions = extendOptions
  Sub.sealedOptions = extend({}, Sub.options)

  //缓存构造函数
  cachedCtors[SuperId] = Sub
  return Sub
}

理解:创建一个Sub继承父级extend、mixin、use、component、directive、filter属性,同时增加superOptions、extendOptions和sealedOptions属性。

2、Vue.nextTick([callback, context])、Vue的set(target, key, value),Vue.delete(target, key) 前面文章已讲过

3、Vue.directive(id, [definition])、Vue.filter(id, [definition])、Vue.component(id, [definition])实现形式相同,而且在Vue源码中,其确实也是在一处实现的

/**
 * Vue.directive()、Vue.filter()、Vue.component()
 */

Vue.options = Object.create(null)

//ASSET_TYPES = ['component', 'directive', 'filter']
ASSET_TYPES.forEach(type => {
  Vue.options[type + 's'] = Object.create(null)
})

ASSET_TYPES.forEach(type => {
  Vue[type] = function (id, definition) {
    if (!definition) {       //获取
      return this.options[type + 's'][id]
    } else {
      if (type === 'component' && isPlainObject(definition)) {    //注册组件
        definition.name = definition.name || id
        definition = Vue.extend(definition)
      }

      if (type === 'directive' && typeof definition === 'function') {   //自定义指令
        definition = {bind:definition, update:definition}
      }

      this.options[type + 's'][id] = definition   //挂载到options上
      return definition
    }
  }
})

4、Vue.use(plugin)

用法:安装Vue.js插件,如果插件是对象须提供install方法,是函数则其自身就为install方法

/**
 * Vue.use(plugin)
 */

 Vue.use = function (plugin) {
   const installPlugins = (this._installPlugins || (this._installPlugins = [])) //  存放全局插件的数组
   if (installPlugins.indexOf(plugin) > -1) {   //    已有该插件直接返回
     return this
   }

   //其他参数
   const args = toArray(arguments, 1)   //除了第一个参数所有参数复制给args
   args.unshift(this)   //将Vue添加到args第一个元素
   if (typeof plugin.install === 'function') {    //  传入的是对象
     plugin.install.apply(plugin, args)
   } else if (typeof plugin === 'function') {     //传入的是方法
     plugin.apply(null, args)
   }
   installPlugins.push(plugin)
   return this
 }

5、Vue.mixin(mixin)

用法:全局注册混入一个mixin,影响注册之后创建的每一个Vue.js实例

 /**
  * Vue.mixin(mixin)
  */

Vue.mixin = function (mixin) {
  this.options = mergeOptions(this.options, mixin)    //将mixin和原本的options合并成一个对象
  return this
}

由于每次创建Vue实例都会跳用initMixin(),从而使得mixin影响注册之后的每一个组件。

6、Vue.version

用法:提供Vue.js安装版本号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值