官方解释:
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
选项合并
- 当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
- 比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
- 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
- 值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
请仔细理解上面选项合并的4点意思,下面会做些实践,帮助理解,其实看官方文档也是可以的
先说明一下,vue组件的data,生命周期钩子函数,methods等都可以在mixin中直接 抽离一份
1.当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
这句话,emm,就是剩下3点的概括
2.比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
最下面有代码仓库,也可以直接下载看
先建立 mixinTest .js
export default {
data(){
return {
title:"title-mixin",
}
},
mounted(){
console.log(this.title,'mixin')
},
}
建立组件HelloWorld.vue,并且局部注册mixin
<template>
<div class="hello">
<div>
{{title}}
//title-hellwWord
</div>
</div>
</template>
<script>
import mixinTest from "./mixinTest"; //导入mixinTest
export default {
name: 'HelloWorld',
props: {
msg: String
},
data(){
return {
title:"title-hellwWord",
}
},
mixins:[mixinTest], //注册mixinTest
mounted(){
console.log(this.title,'hellwWord')
},
}
</script>
此时页面展示的是 title-hellwWord,而不是title-mixin。说明,mixin的值被组件的值给覆盖了。
再来看一下这句 数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先,
现在就容易理解了,如果没有相同的就合并,冲突就以组件数据优先
这时其实还可以看出一点,不论是在mixin还是在组件里,都可以相互通过 this调用,比如data的值,methods的方法(下面会有实验)
3.同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
依然在刚才的代码上做些改动
mixinTest.js
export default {
created() {
console.log('created-mixin')
},
mounted(){
console.log('mounted-mixin')
},
}
组件 HelloWorld.vue
<template>
<div class="hello">
</div>
</template>
<script>
import mixinTest from "./mixinTest";
export default {
name: 'HelloWorld',
mixins:[mixinTest],
mounted(){
console.log('mounted-hellwWord')
},
}
</script>
//页面console.log打印的
created-mixin
mounted-mixin
mounted-hellwWord
如下图:
再来看一下这句话 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
不论是mixinTest还是HelloWorld的生命周期钩子函数都执行了,并且就算有同名冲突的,也不会覆盖,而是都调用,而且
混入对象的钩子将在组件自身钩子之前调用
4.值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
继续在这里插入代码片
mixinTest.js
export default {
methods:{
_addNum(){
this.num = this.num + 2
//这个函数不会执行,会被 HelloWorld组件给覆盖掉,
},
//个函数会被HelloWorld组件调用
_addNumMixin(){
//然后在调用HelloWorld组件的_addNum这个方法
//是mixin的方法哦
this._addNum()
},
},
}
HelloWorld.vue
<template>
<div class="hello">
<button @click="_addNum">点击加1</button>
<br/>
<button @click="_addNumMixin">minxi 点击加1</button>
<br/>
<span>{{num}}</span>
</div>
</template>
<script>
import mixinTest from "./mixinTest";
export default {
name: 'HelloWorld',
data(){
return {
num:1,
}
},
mixins:[mixinTest],
methods:{
//会覆盖 mixin的这个方法
_addNum(){
this.num++
},
},
}
</script>
通过上面的例子,再看一下
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对
当methods的方法相同时,会被HelloWorld组件覆盖mixin,不相同时,就是合并,就像object.assign()合并对象一样;
通过上面例子可以发现,他们可以通过this,相互调用方法,data等;还是挺好用的,和react的高阶组件也有点类似。
可以直接下载我的代码看
仓库地址