Vue源码02-静态方法和mergeOptions

通过上节我们对Vue的流程有了一个大概的了解,这节我们将进一步分析

Vue的静态方法

Vue.use

在我们写Vue项目的时候,应该都会用到这个东西,它的作用只有一个就是给我项目注册插件

  Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    } 

    const args = toArray(arguments, 1)
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args) 
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
  }
  • 注册插件的时候,我们会存一个数组,用来判断是否已经存储了
  • 如果插件有install方法我们把Vue当成第一个参数传给插件,并调用install方法
  • 没有install,它本事是一个function,我们直接调用
Vue.mixin

不推荐在应用代码中使用

 Vue.mixin = function (mixin: Object) {
    this.options = mergeOptions(this.options, mixin)
    return this
  }
  • 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例
Vue.extend

使用基础 Vue 构造器,创建一个“子类”。

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 Sub = function VueComponent (options) {
      this._init(options)
    }
    .....
   cachedCtors[SuperId] = Sub
    return Sub
  }
  • 判断extendOptions_ _Ctor[SuperId]是否存在,存在直接拿去
  • 生成Sub函数,
  • 对Sub的options以及方法初始化(具体可以查看源码,比较简单)
  • 返回Sub
Vue.component(),Vue.directive(),Vue.filter()
  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 = this.options._base.extend(definition)
        }
        if (type === 'directive' && typeof definition === 'function') {
          definition = { bind: definition, update: definition }
        }
        this.options[type + 's'][id] = definition
        return definition
      }
    }
  })

这里可以去看看官网对这几个静态方法的案例讲解,你就会非常清楚了

Vue.prototype._init

mergeOptions
export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  ...
  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  
 ...
  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
}

  • normalizeProps格式化props
  • normalizeInject格式化inject
  • normalizeDirectives格式化directives
  • mergeField合并函数,对每一个key采用对应的strats函数进行合并
strats是一个对象
activated: ƒ mergeHook( parentVal, childVal )
beforeCreate: ƒ mergeHook( parentVal, childVal )
beforeDestroy: ƒ mergeHook( parentVal, childVal )
beforeMount: ƒ mergeHook( parentVal, childVal )
beforeUpdate: ƒ mergeHook( parentVal, childVal )
components: ƒ mergeAssets( parentVal, childVal, vm, key )
computed: ƒ ( parentVal, childVal, vm, key )
created: ƒ mergeHook( parentVal, childVal )
data: ƒ ( parentVal, childVal, vm )
deactivated: ƒ mergeHook( parentVal, childVal )
destroyed: ƒ mergeHook( parentVal, childVal )
directives: ƒ mergeAssets( parentVal, childVal, vm, key )
el: ƒ (parent, child, vm, key)
errorCaptured: ƒ mergeHook( parentVal, childVal )
filters: ƒ mergeAssets( parentVal, childVal, vm, key )
inject: ƒ ( parentVal, childVal, vm, key )
methods: ƒ ( parentVal, childVal, vm, key )
mounted: ƒ mergeHook( parentVal, childVal )
props: ƒ ( parentVal, childVal, vm, key )
propsData: ƒ (parent, child, vm, key)
provide: ƒ mergeDataOrFn( parentVal, childVal, vm )
serverPrefetch: ƒ mergeHook( parentVal, childVal )
updated: ƒ mergeHook( parentVal, childVal )
watch: ƒ ( parentVal, childVal, vm, key )
data,provide合并
// 代码截取
  if (!childVal) {
      return parentVal
    }
    if (!parentVal) {
      return childVal
    }
  ...
  //mergeData
  if (!hasOwn(to, key)) {
      set(to, key, fromVal) // 响应式添加
    } else if (
      toVal !== fromVal &&
      isPlainObject(toVal) &&
      isPlainObject(fromVal)
    ) {
      mergeData(toVal, fromVal) // 递归赋值
    }
  • 如果parentVal不存在,返回childVal
  • 如果childVal不存在,返回parantVal
  • 如果都存在,遍历parantVal的key
    • 如果childVal不存在key,则把parantVal的这个属性响应式赋值给childVal
    • 如果childVal存在key,对应的值不相等并且是对象,则递归这个对象进行赋值
    • 最后返回childVal
props,methods,inject,computed合并
 if (!parentVal) return childVal
  const ret = Object.create(null)
  extend(ret, parentVal)
  if (childVal) extend(ret, childVal)
  return ret
  • 如果parentVal不存在,则返回childVal
  • 如果childVal不存在,则返回parentVal
  • 创建一个对象把parentVal,childVal继承返回,后者覆盖前者
'beforeCreate', 'created', 'beforeMount', 'mounted','beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated', 'errorCaptured', 'serverPrefetch'合并
 const res = childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : Array.isArray(childVal)
        ? childVal
        : [childVal]
    : parentVal
  return res
    ? dedupeHooks(res)
    : res
// dedupeHooks
function dedupeHooks (hooks) {
  const res = []
  for (let i = 0; i < hooks.length; i++) {
    if (res.indexOf(hooks[i]) === -1) {
      res.push(hooks[i])
    }
  }
  return res
}

  • childVal不存在,返回parentVal
  • parentVal不存在,返回[childVal]
  • 都存在采用合并数组,parentVal.concat(childVal)
  • dedupeHooks排重
'component', 'directive', 'filter'合并
  const res = Object.create(parentVal || null)
  if (childVal) {
    return extend(res, childVal)
  } else {
    return res
  }
  • childVal不存在,返回parentVal
  • parentVal不存在,返回childVal
  • 如果都存在,继承parentVal,childVal,后者覆盖前者

小节:

  • 了解Vue的静态方法
  • mergeOptions对options合并规则

你可能感兴趣的:(Vue源码02-静态方法和mergeOptions)