This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

1. Introduction

Official documentation analysis of Vue source code, always encounter these global API calls, so first analyze it.

A global API is a static method mounted on a Vue, roughly as follows

  1. Set adds or modifies the value of an attribute of an object such thatpropertyIt is also reactive and triggers view updates
  2. Delete Deletes an attribute of an object and triggers an update
  3. NextTick puts the callbacks together in an array, next onetickTo call back one by one in the order in which they are added
  4. Observable makes an object reactive
  5. Use registered plug-in
  6. Mixin options
  7. The extend to generateVueA subclass

The remaining three ‘components ‘, ‘directive’, and ‘filter’ are dedicated to articles

2. set

The official documentation

This method is mounted on both the static and instance Vue

/ / static
Vue.set = set
/ / instance
Vue.prototype.$set = set
Copy the code
//
/** * Set a property on an object. Adds the new property and * triggers change notification if the property doesn't * already exist. */
export function set(
  target: Array<any> | Record<string.any>,
  key: any,
  val: any
) :any {
  // Set the array index value
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // Index may be set to be greater than the length of the array
    target.length = Math.max(target.length, key)
    // The array's splice method can listen for changes
    target.splice(key, 1, val)
    return val
  }
  if (key intarget && ! (keyin Object.prototype)) {
    // If key is an inherent property of target, it can be assigned directly because target is reactive
    target[key] = val
    return val
  }
  const ob = (target as any).__ob__
  if(! ob) {// Target is not a reactive value
    target[key] = val
    return val
  }
  // make val responsive
  defineReactive(ob.value, key, val)
  // Target triggers a notification
  ob.dep.notify()
  return val
}
Copy the code

Summary: It is used to assign a value to an object’s properties, triggering its update notification if the object is responsive

Note: We cannot assign values to Vue instances or $data. For stability, we cannot assign values to Vue instances or $data

3. delete

The official documentation

This method is mounted on both the static and instance Vue

/ / static
Vue.delete = del
/ / instance
Vue.prototype.$delete = del
Copy the code
/** * Delete a property and trigger change if necessary. */
export function del(target: Array<any> | Object, key: any) {
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // The array method is deleted, and the modification triggers the update
    target.splice(key, 1)
    return
  }
  const ob = (target as any).__ob__

  if(! hasOwn(target, key)) {// The deleted attribute does not exist
    return
  }
  delete target[key]
  if(! ob) {// The object with the deleted attribute is not responsive
    return
  }
  // If it is reactive, trigger an update
  ob.dep.notify()
}
Copy the code

Summary: It is used to remove the properties of an object and trigger its update notification if the object is responsive

Note: You cannot delete Vue instance attributes or $data attributes. For stability, you cannot delete application exceptions

4. nextTick

See my previous article

5. extend

The official documentation

This method is only mounted on Vue static

/** * Using the base Vue constructor, create a "subclass". This is not strictly a subclass, as it is not inherited from *@param ExtendOptions Extended component Options *@returns Return the extended subclass */
Vue.extend = function (extendOptions: any) :Component {
  extendOptions = extendOptions || {}
  const Super = this
  const SuperId = Super.cid
  // Cache the extended subclass on the extended object. If you extend the same object on the same parent class, you can use cache
  const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
  if (cachedCtors[SuperId]) {
    return cachedCtors[SuperId]
  }

  const name = extendOptions.name || Super.options.name

  // Define a subclass, which will be returned
  const Sub = (function VueComponent(this: any, options: any) {
    this._init(options)
  } as unknown) as Component
  // If the parent class is inherited in this way, modifying the parent class does not affect the parent class. Modifying the parent class does affect the lookup of the child class's prototype methods
  Sub.prototype = Object.create(Super.prototype)
  // fix constructor to point otherwise to the parent class
  Sub.prototype.constructor = Sub
  // Every Vue class (subclass) has a CID that identifies uniqueness. The CID of a Vue is 0, and the subclass is incremented
  Sub.cid = cid++
  // merge options from the parent class into subclasses
  Sub.options = mergeOptions(Super.options, extendOptions)
  / / specify the parent class, in only one place USES, resolveConstructorOptions _init
  Sub['super'] = Super

  // For props and computed properties, we define the proxy getters on
  // the Vue instances at extension time, on the extended prototype. This
  // avoids Object.defineProperty calls for each instance created.
  if (Sub.options.props) {
    initProps(Sub)
  }
  if (Sub.options.computed) {
    initComputed(Sub)
  }

  // allow further extension/mixin/plugin usage
  // Subclasses can extend subclasses
  Sub.extend = Super.extend
  Sub.mixin = Super.mixin
  Sub.use = Super.use

  // create asset registers, so extended classes
  // can have their private assets too.
  ASSET_TYPES.forEach(function (type) {
    Sub[type] = Super[type]})// enable recursive self-lookup
  if (name) {
    Sub.options.components[name] = Sub
  }

  // keep a reference to the super options at extension time.
  // later at instantiation we can check if Super's options have
  // been updated.
  Sub.superOptions = Super.options
  Sub.extendOptions = extendOptions
  Sub.sealedOptions = extend({}, Sub.options)

  // cache constructor
  // Cache this subclass
  cachedCtors[SuperId] = Sub
  return Sub
}
Copy the code

Summary: To extend the subclass, all custom components are obtained through this method

When you analyze components in the future, you can go further

6. use

The official documentation

This method is only mounted on Vue static

Vue.use = function (plugin: Function | any) {
  // Read cache
  const installedPlugins =
    this._installedPlugins || (this._installedPlugins = [])
  // If the plugin has been installed in the cache, return it directly
  if (installedPlugins.indexOf(plugin) > -1) {
    return this
  }

  // additional parameters
  // 得到 [this, ...arguments]
  const args = toArray(arguments.1)
  args.unshift(this)
  // When the plug-in executes, the first argument is Vue, and the rest is passed in when the plug-in is installed
  if (typeof plugin.install === 'function') {
    plugin.install.apply(plugin, args)
  } else if (typeof plugin === 'function') {
    plugin.apply(null, args)
  }
  // Cache the plug-in
  installedPlugins.push(plugin)
  return this
}
Copy the code

There are no plug-ins installed inside the Vue code

We can package any enhancements to Vue as “plug-ins “.

7. mixin

The official documentation

Register a global blend, the code is extremely simple

Vue.mixin = function (mixin: Object) {
  // Merge incoming mixins into options
  this.options = mergeOptions(this.options, mixin)
  return this
}
Copy the code

There are no options mixed into the code inside Vue

8. compile

The official documentation

Compile the template string into the render function

Vue.compile = compileToFunctions
Copy the code

It’s a big hole. I’ll write about it later

9. observable

The official documentation

To make an object reactive

Vue.observable = <T>(obj: T): T= > {
  observe(obj)
  return obj
}
Copy the code

So a responsive object, which is reading its properties is known to it, and when its properties change, it tells it where it’s reading its properties, and if that place needs to be, you can do something, like in render, it rerenders, in computed, it recalculates, In Watch, the function will be triggered to execute again. These three places are the only ones that are not needed. In Vue, the dep. target is used to mark whether there is a need.

Leave a hole here, too

10. The last

This is just the first glimpse of the static methods on Vue, leaving three (five) holes that will be filled in later.

Attached are several articles I wrote earlier

  1. Vue2 source code analysis nextTick
  2. Code snippet JS flow limiting scheduler
  3. Linked Lists of Data Structures and Algorithms (1)
  4. Vue2 source code parsing event system $on