Vue Mix

Mixins provide a very flexible way to distribute reusable functionality in Vue components. A mixin object can contain arbitrary component options. When a component uses a mixin object, all options for the mixin object will be “mixed” into the options of the component itself.

First paste an official tutorial and my understanding of this tutorial

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Define a mixed object
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}

Define a component that uses mixed objects
var Component = Vue.extend({
mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"

In this sample code, you first define a mix that includes a created and a method, and then use mixins to import the mix in the component that needs to use the code, so that you can use the mix in the component everything in it.

This is actually a bit like inheritance in Java. Mixing is similar to a parent class, and a component is equivalent to a subclass. The component has all the behaviors of mixing, including function, lifecycle, event monitoring, etc. At the same time, we can rewrite the content in the component.

Option merge

When components and mixed objects contain options with the same name, these options will be “merged” in an appropriate manner.

For example, data objects will perform recursion merging internally and prioritize component data in case of conflict.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}

new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})

The hook functions with the same name will be merged into an array, so they will all be called. Also, the hook of the mixed object will be called before the component itself hooks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var mixin = {
created: function () {
Console.log ('The hook of the mixed object is called')
}
}

new Vue({
mixins: [mixin],
created: function () {
Console.log ('component hook called')
}
})

// => " the hook of the mixed object is called "
// => " component hook is called "

Options whose value is an object, such as’methods’, ‘components’, and’directives’, will be merged into the same object. When the key names of the two objects conflict, the Attribute - Value Pair of the component object is taken.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}

var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

Global mixing

Mixing can also be registered globally. Use caution when using it! Once global mixing is used, it will affect every Vue instance created after **. When used properly, this can be used to inject processing logic into custom options.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Inject a processor for the custom option'myOption '.
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})

new Vue({
myOption: 'hello!'
})
// => "hello!"

extend/component/mixin/extends

The same example from the beginning, but to avoid confusion, our current object name is not myMixin, but myOption.

new

New Vue (myOption): actually instantiates a component

Vue.component is a method for registering or obtaining global components, which means that the extension instance constructor generated by Vue.extend is registered as a component, which can be used in all components that are later than the component registration, such as:

1
2
3
4
5
Vue.component('global-component', Vue.extend(myOption));
//Pass an option object (automatically call Vue.extend), equivalent to upstream code.
Vue.component('global-component', myOption);
//Get the registered component (always return the constructor)
var MyComponent = Vue.component('global-component')

extend

1
2
3
4
5
6
7
8
9
10
11
let MyComponent = Vue.extend(myOption);
Based on the basic component MyComponent, and then expand the new logic.
new MyComponent({
created(){
//do something
console.log('onCreated-2');
}
//Other custom logic
});
// -> onCreated-1
// -> onCreated-2

mixins

The rules for merging are the same as for extending

1
2
3
4
5
6
7
8
9
10
new Vue({
mixins: [myOption],
created(){
//do something
console.log('onCreated-2');
}
//Other custom logic
});
// -> onCreated-1
// -> onCreated-2

extends

This is similar to mixins, except that the options of the component itself will have higher priority than the source component to be extended. Also extends accepts an object instead of an array.

1
2
3
4
5
6
7
8
9
10
new Vue({
extends: myOption,
created(){
//do something
console.log('onCreated-2');
}
//Other custom logic
});
// -> onCreated-1
// -> onCreated-2

Priority

extend > extends > mixins

Reference article:

https://segmentfault.com/a/1190000010095089