current position:Home>Source code analysis, Vue What happens when using (), take initializing vuex as an example

Source code analysis, Vue What happens when using (), take initializing vuex as an example

2022-04-29 04:27:59@huihui_ new

understand Vue.use Methods and principles for development vue Plug ins are very helpful ,Vue.use The method is to initialize Vue overall situation API(initGlobalAPI) Hang up when you're ready Vue above , The code is as follows :

/* @flow */

import {
     toArray } from '../util/index'

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

    // additional parameters
    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
  }
}

This method can be divided into two steps :
1. First of all, will Vue Of _installedPlugins Property assigned to _installedPlugins Variable , Without this attribute, an empty array is initialized . Some words , Then judge whether the plug-in has been installed , Once installed, return directly to , Avoid re installation .
2.args Is to store additional passed parameters , That is to say Vue.use(‘name’, args) Parameters can be passed when ; The first parameter is this, That is to say class Vue. Next , Determine whether the plug-in has install Method , If so, execute the plug-in directly install Method , stay vuex During the initialization process of install Methodical , The code is as follows :

Vue.use(Store)
export function install (_Vue) {
    
  if (Vue && _Vue === Vue) {
    
    if (process.env.NODE_ENV !== 'production') {
    
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

This code also determines whether it has been installed vuex, If it is installed, it will give a warning , Otherwise, the incoming _Vue Assign a value to a variable Vue( for the first time install When Vue by undefined), Next applyMixin(), The code is as follows :

export default function (Vue) {
    
  const version = Number(Vue.version.split('.')[0])

  if (version >= 2) {
    
    Vue.mixin({
     beforeCreate: vuexInit })
  } else {
    
    // override init and inject vuex init procedure
    // for 1.x backwards compatibility.
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {
     }) {
    
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }

  /** * Vuex init hook, injected into each instances init hooks list. */

  function vuexInit () {
    
    const options = this.$options
    // store injection
    if (options.store) {
    
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
    
      this.$store = options.parent.$store
    }
  }
}

This code first determines vuex Version of , I'm just going to analyze 2 Version above , Used Vue.mixin() In the hook function beforeCreate Added in vuexInit Method , stay beforeCreate Trigger when executing ,vuexInit It ensures that all components can pass this.$store To visit Store object . that beforeCreate How to join Vue What about the middle , Then look at Vue.mixin Source code ( Actually Vue Of mixin Grammatical principles are also used Vue.mixin Method ):

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

export function mergeOptions (
  parent: Object, child: Object, vm?: Component
): Object {
    
  if (process.env.NODE_ENV !== 'production') {
    
    checkComponents(child)
  }

  if (typeof child === 'function') {
    
    child = child.options
  }

  //  Here we normalize some properties 
  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  const extendsFrom = child.extends
   //  Children, if any extends attribute , Then recursively call mergeOptions
  if (extendsFrom) {
    
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  //  Children, if any mixins attribute , Then recursively call mergeOptions
  if (child.mixins) {
    
    for (let i = 0, l = child.mixins.length; i < l; i++) {
    
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  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
}

Vue.mixin Is mainly used in mergeOptions( Merge configuration ) Method ,mergeOptions Some properties are normalized in ( I won't go into more details here ), stay vuex During the initialization of, we mainly focus on :

for (key in parent) {
    
    mergeField(key)
  }

This is the time parent Actually Vue There is already a hook function on the beforeCreate( stay Vue Generated in the process of instantiation ), perform mergeField

/** * Option overwriting strategies are functions that handle * how to merge a parent option value and a child option * value into the final value. */
var strats = config.optionMergeStrategies;

LIFECYCLE_HOOKS.forEach(function (hook) {
    
  strats[hook] = mergeHook;
});

function mergeHook (
  parentVal, childVal
) {
    
  var res = childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : Array.isArray(childVal)
        ? childVal
        : [childVal]
    : parentVal;
  return res
    ? dedupeHooks(res)
    : res
}

For different properties ,Vue There are different merger strategies , stay vuex install Only focus on the merging strategy of hook functions , Because what's coming in is Vue.mixin({ beforeCreate: vuexInit }). The consolidation strategy is as follows , When the child element has a value and the parent element has a value ,concat Two hook functions , The final beforeCreate It's actually an array . It's triggering beforeCreate The process of is actually traversal beforeCreate This hook array , The functions in the array are executed in turn ,( For the hook function of parent-child components, the trigger timing principle is actually similar to this ).

copyright notice
author[@huihui_ new],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/117/202204270551339314.html

Random recommended