Mixin混入
基础
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
组件选项:指的是组件对象中的 data
、created
、methods
等等选项。
可通过 this.$options
查看选项
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var myMixin = { created: function () { this.hello() }, methods: { hello: function () { console.log('hello from mixin!') } } }
var Component = Vue.extend({ mixins: [myMixin] })
var component = new Component()
|
通俗讲,就是把组件的部分代码抽离出来,再”混合”进入组件。当多个组件有相同的选项代码时,可以把相同的选项代码抽离到一个文件,再混入到每个组件,从而达到共享部分代码的目的。
选项合并
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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) } })
|
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var mixin = { created: function () { console.log('混入对象的钩子被调用') } }
new Vue({ mixins: [mixin], created: function () { console.log('组件钩子被调用') } })
|
值为对象的选项,例如 methods
、components
和 directives
,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
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() vm.bar() vm.conflicting()
|
注意:Vue.extend()
也使用同样的策略进行合并。
某项目中使用的Mixin示例
抽离各组件相同的代码:
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
| export const playlistMixin = { computed: { ...mapGetters([ 'playlist' ]) }, mounted() { this.handlePlaylist(this.playlist) }, activated() { this.handlePlaylist(this.playlist) }, watch: { playlist(newVal) { this.handlePlaylist(newVal) } }, methods: { handlePlaylist() { throw new Error('component must implement handlePlaylist method') } } }
|
混入到组件:
1 2 3 4 5 6 7 8 9 10
| import { playlistMixin } from '@/common/js/mixin' export default { mixins: [playlistMixin], methods: { handlePlaylist(playlist) { ... } } }
|