美文网首页
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

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