Vue.use

Purpose: Plug-in installation

The source code:

Vue.use = function (plugin: Function | Object) {
  const installedPlugins =
    this._installedPlugins || (this._installedPlugins = []); // All plugins are stored in the vue._installedplugins queue
  if (installedPlugins.indexOf(plugin) > -1) { // Avoid repeated installation
    return this;
  }
  // Start with the second parameter as passed in to the plug-in
  const args = toArray(arguments.1);
  args.unshift(this); // Pass the Vue constructor as the first argument
  // If the plug-in implements install
  if (typeof plugin.install === "function") {
    plugin.install.apply(plugin, args);
  }
  // if the plugin function is a function, it is called
  else if (typeof plugin === "function") {
    plugin.apply(null, args);
  }
  installedPlugins.push(plugin);
  return this;
};
Copy the code

Explanation: a detailed explanation see code comments, as can be seen from the source Vue maintains a queue to hold all the plugin installation, the installation of the plug-in is actually perform the plug-in install method (the premise is a plug-in implements the method) or direct execution plugin function, it will receive a series of parameters, one of the first parameter to the Vue constructor

Vue.mixin

Action: Merges passed options and vue.options

The source code:

function mergeOptions (
  parent: Object,
  child: Object, vm? : Component) :Object {
  if (typeof child === 'function') {
    child = child.options
  }

  normalizeProps(child, vm) // The normalized props will finally output the type {key: {type: String, default: '}}
  normalizeInject(child, vm) // Standardize inject
  normalizeDirectives(child) // Standardized directives
  const extendsFrom = child.extends
  if (extendsFrom) { // merge child.extends separately
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  if (child.mixins) { // If child defines mixins, they are merged with parent first to reduce their priority
    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) } }// Call different merge strategy methods for different types of options to merge
  function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}
Vue.mixin = function (mixin: Object) {
  this.options = mergeOptions(this.options, mixin);
  return this;
};
Copy the code

Vue. Mixin is used to merge options and Vue. Options passed in, extending Vue

As for calling different merge strategy methods for different types of options mentioned in the comment, here are a few merge strategies:

// Override the target object's properties with the source object's properties
function extend (to: Object, _from: ?Object) :Object {
  for (const key in _from) {
    to[key] = _from[key]
  }
  return to
}

// Resource merge: the source object is the prototype of the target object, and the target object is not overwritten
// The options combined using this policy are: Components, directives, filters
function mergeAssets (
  parentVal: ?Object,
  childVal: ?Object, vm? : Component, key: string) :Object {
  const res = Object.create(parentVal || null)
  if (childVal) {
    return extend(res, childVal)
  } else {
    return res
  }
}

// Default merge: if the target object is undefined the source object is used directly, otherwise the target object is used
// The options merged using this policy are: _base
function defaultStrat (parentVal: any, childVal: any) :any {
  return childVal === undefined
    ? parentVal
    : childVal
}

// overwrite merge: Target object properties overwrite source object properties
// The options that use this policy are props, methods, Inject, and computed
function merge (
  parentVal: ?Object,
  childVal: ?Object, vm? : Component, key: string): ?Object {
  if(! parentVal)return childVal
  const ret = Object.create(null)
  extend(ret, parentVal)
  if (childVal) extend(ret, childVal)
  returnret } ... Other merge strategies are not described muchCopy the code

Extension: use of vue.options

The first step in creating a Vue instance is to merge options passed in by the user with vue. options, meaning that the globally defined vue. options will be accessible in each instance

// The mergeOPtions method is described above
vm.$options = mergeOptions(
    vm.constructor.options, // This is not easy to understand in the source code
    options || {},
    vm
)
Copy the code

Vue.extend

Creates a VUE component constructor

The source code:

Vue.extend = function (extendOptions: Object) :Function { // The parameter is user-defined component options
  extendOptions = extendOptions || {};
  const Super = this; // This points to Vue
  const SuperId = Super.cid; // The unique identifier of Vue
  const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}); / / cache
  // Read cache first, if there is a cache, return cache directly
  if (cachedCtors[SuperId]) {
    return cachedCtors[SuperId];
  }

  // name: component name
  const name = extendOptions.name || Super.options.name;

  // Sub inherits from Vue (super)
  const Sub = function VueComponent(options) {
    this._init(options); // this._init inherits from Vue
  };
  Sub.prototype = Object.create(Super.prototype);
  Sub.prototype.constructor = Sub;
  Sub.cid = cid++;
  // Merge vue. options and Component, the same merge method called in vue. mixin, as described in the vue. mixin section
  Sub.options = mergeOptions(Super.options, extendOptions);
  Sub["super"] = Super;

  // This is a layer proxy for props, computed sub. key --> sub._props
  if (Sub.options.props) {
    initProps(Sub);
  }
  if (Sub.options.computed) {
    initComputed(Sub);
  }

  // copy Vue static methods to Sub
  Sub.extend = Super.extend;
  Sub.mixin = Super.mixin;
  Sub.use = Super.use;

  // Sub.component = Vue.component Sub.directive = Vue.directive Sub.filter = Vue.filter
  ASSET_TYPES.forEach(function (type) {
    Sub[type] = Super[type];
  });
  // Make sure it loops
  if (name) {
    Sub.options.components[name] = Sub;
  }

  // Keep references to vue. options and options passed in by the user
  Sub.superOptions = Super.options;
  Sub.extendOptions = extendOptions;
  Sub.sealedOptions = extend({}, Sub.options);

  cachedCtors[SuperId] = Sub; / / cache
  // Return value is a constructor
  return Sub;
};
Copy the code

Explanation: See code comments for details

Vue.component & Vue.directive & Vue.filter

Note: These three static methods are put together. In Vue, the global component, directive, and filter are all called assets. They share one method

The source code:

const ASSET_TYPES = [
  'component'.'directive'.'filter'
]

ASSET_TYPES.forEach((type) = > {
  Vue[type] = function (
    id: string,
    definition: Function | Object
  ) :Function | Object | void {
    if(! definition) {return this.options[type + "s"][id]; Vue.options.components[id]
    } else {
      if (type === "component" && isPlainObject(definition)) {
        definition.name = definition.name || id;
        definition = this.options._base.extend(definition); // Call vue.extend for component to create component constructor
      }
      if (type === "directive" && typeof definition === "function") {
        definition = { bind: definition, update: definition };
      }
      this.options[type + "s"][id] = definition; // Save the new definition globally
      returndefinition; }}; });Copy the code

other

Vue.set === Vue.prototype.$set

Vue.delete === Vue.prototype.$delete

Vue.nextTick === Vue.prototype.$nextTick