美文网首页
Vue源码02-静态方法和mergeOptions

Vue源码02-静态方法和mergeOptions

作者: 熊少年 | 来源:发表于2020-05-22 10:56 被阅读0次

通过上节我们对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

    通过上节我们对Vue的流程有了一个大概的了解,这节我们将进一步分析 Vue的静态方法 Vue.use 在我们写Vu...

  • 2018-07-02 Vue源码解析阅读笔记

    合并配置 在new Vue()初始化时,会通过mergeOptions()的方法,把全局变量、全局方法、全局组件等...

  • vue源码:探究mixin与mergeOptions

    vue中的mixin可以实现一些逻辑复用,我们来看看mixin的好处和一些不足。 优点: 可以提取一些功能(组件)...

  • Vue源码分析(3)--选项合并过程mergeOptions

    前言 本文是vue2.x源码分析的第三篇,主要讲解选项合并过程mergeOptions! 先看调用形式 1、执行r...

  • day14-类和对象

    02-类方法和静态方法 类中方法有三种:对象方法,类方法,静态方法 1.对象方法 声明在类中有默认参数self通过...

  • 【读vue 源码】溯源 import Vue from 'vue

    阅读资源 vue.js源码托管地址 flow 静态检查工具地址 rollup 源码构建 flow 静态检查工具 f...

  • vue源码解析(一)

    vue源码解析(一) 先决条件 需要能够熟悉使用 vue ,了解vue属性和方法。 带着问题去看源码 熟悉ES6或...

  • Vue源码阅读(三)

    前言   前面两篇文章是关于构造函数Vue初始化过程中做了什么,其中涉及到mergeOptions这个方法,它将策...

  • Vue源码浅析01

    Vue源码大致可以理解分为:初始化属性、方法(Vue.use、***等等)和实例化(new Vue)执行的一些方法...

  • 阅读Vue源码--前置知识

    Flow[https://flow.org/] 认识 FlowJavaScript 静态类型检查器,vue 源码利...

网友评论

      本文标题:Vue源码02-静态方法和mergeOptions

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