There are two more advanced static methods in Vue, mixin and extend. Let’s discuss their principles and usage scenarios.

Mixins:

Principle:

Let’s take a look at the official website:

Parameter: {Object} mixin

Usage:

Mixin can also be registered globally. Use with extreme care! Once global mixin is used, it affects every subsequent Vue instance created. When used appropriately, this can be used to inject processing logic for custom options.

     // Inject a handler for the custom option 'myOption'.
     Vue.mixin({
       created: function () {
         var myOption = this.$options.myOption
         if (myOption) {
           console.log(myOption)
         }
       }
     })
     
     new Vue({
       myOption: 'hello! '
     })
     // => "hello!"
Copy the code

Mixin initializes the Vue instance by merging the mixin object into options.

// src\core\global-api\mixin.js
 export function initMixin (Vue: GlobalAPI) {
   Vue.mixin = function (mixin: Object) {
     this.options = mergeOptions(this.options, mixin)
     return this}}Copy the code
 // src\core\instance\index.js
 function Vue (options) {
     if(process.env.NODE_ENV ! = ='production' &&
     !(this instanceof Vue)
     ) {
     warn('Vue is a constructor and should be called with the `new` keyword')}this._init(options)
 }
 
 initMixin(Vue)
 ...
 
 export default Vue
Copy the code

That is, mixins are simply an extension of the configuration objects we pass in when we initialize Vue instances.

As in the example above, we pass a created check function inside a configuration object called vue. mixin. From the source we can see that the object passed in will eventually be merged with the option (via the mergeOptions method in the source above) when we initialize the new Vue(options) and stored in the option.

Usage Scenarios:

Mixins are used when we need to globally inject methods, filters, or hooks. For example, if we wanted each Vue instance to have a print method, we could do this:

    Vue.mixin({
        methods: {
            print() {
                console.log('I'm a mixin injection method! `)}}})Copy the code

Or if we want to listen for which components are loaded, unloaded, and so on at what stage, we can do this:

    Vue.mixin({
        mounted() {
            console.log(`The ${this.$route.name}component mounted! `)
        },
        destroyed() {
            console.log(`The ${this.$route.name}component destroyed! `)}})Copy the code

If we do not want to mix these configuration options into every component instance, but just individual components, it is best not to use mixins, which may affect the performance of our components.

The Extend:

Principle:

Let’s take a look at the official website:

Parameters: {Object} options

Usage:

Using the base Vue constructor, create a “subclass.” The parameter is an object that contains component options.

The data option is a special case, note – it must be a function in vue.extend ().

Data must be functions in order to prevent individual instances of data clutter, closure applications.

<div id="mount-point"></div>
// Create a constructor
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>'.data: function () {
    return {
      firstName: 'Walter'.lastName: 'White'.alias: 'Heisenberg'}}})// Create a Profile instance and mount it to an element.
new Profile().$mount('#mount-point')
Copy the code

Look again inside the source code on vue. extend implementation:

Vue.extend = function (extendOptions: Object) :Function {
    extendOptions = extendOptions || {}
    const Super = this
    const SuperId = Super.cid
    const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
    if (cachedCtors[SuperId]) {
      return cachedCtors[SuperId]
    }

    const name = extendOptions.name || Super.options.name
    if(process.env.NODE_ENV ! = ='production' && name) {
      validateComponentName(name)
    }

    const Sub = function VueComponent (options) {
      this._init(options)
    }
    Sub.prototype = Object.create(Super.prototype)
    Sub.prototype.constructor = Sub
    Sub.cid = cid++
    Sub.options = mergeOptions(
      Super.options,
      extendOptions
    )
    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
    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
    cachedCtors[SuperId] = Sub
    return Sub
  }
}
Copy the code

First, we can see that the Sub returned by extend is a constructor that extends from Vue, which means that extend returns a subclass of Vue.

    Sub.prototype = Object.create(Super.prototype)
    Sub.prototype.constructor = Sub
Copy the code

These two lines of code is actually the implementation of Sub to Vue inheritance, there is a line of source code is

    const Super = this
Copy the code

So Super here means Vue.

Sub.options = mergeOptions(
     Super.options,
     extendOptions
)
Copy the code

Note that extend also merges the passed configuration options with Vue’s original options.

Usage Scenarios:

When we don’t need to mix in some configuration globally, for example, we want to get a Component. We can use Vue.component() or vue.extend ().

constChildVue = Vue.extend({ ... options })newChildVue({ ... options })Copy the code

Note that extend gets a subclass of Vue, the constructor.

The difference between:

A mixin is a mixin of Vue class options. All Vue instance objects will have the configuration behavior blended in.

Extend extends a subclass that extends from the Vue class and affects only the instance objects of that subclass, not the Vue class itself or the instance objects of the Vue class.