一:什么是Mixin?
1.1 官方解释
1.2 自行理解:
将组件的公共逻辑或者配置提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗余度,也可以让后期维护起来更加容易。
这里需要注意的是:提取的是逻辑或配置,而不是HTML代码和CSS代码。其实大家也可以换一种想法,mixin就是组件中的组件,Vue组件化让我们的代码复用性更高,那么组件与组件之间还有重复部分,我们使用Mixin在抽离一遍。
1.3Mixin和Vuex的区别?
上面一点说Mixin就是一个抽离公共部分的作用。在Vue中,Vuex状态管理似乎也是做的这一件事,它也是将组件之间可能共享的数据抽离出来。两者看似一样,实则还是有细微的区别,区别如下:
- Vuex公共状态管理,如果在一个组件中更改了Vuex中的某个数据,那么其它所有引用了Vuex中该数据的组件也会跟着变化。
- Mixin中的数据和方法都是独立的,组件之间使用后是互相不影响的。
二:Mixin的使用
2.1 mixin定义
src目录下新建mixin文件夹,然后新建index.js文件
index.js完整代碼
export const mixins = {
data() {
return {
msg: "我是Mixin中的msg",
};
},
computed: {},
created() {
console.log("我是Mixin中的created生命周期函数");
},
mounted() {
console.log("我是Mixin中的mounted生命周期函数");
},
methods: {
clickMiXin() {
console.log("我是Mixin中的点击事件");
},
},
};
2.2 局部混入
index.vue文件引入代码
<template>
<div>
<el-button @click="clickMiXin">测试</el-button>
</div>
</template>
<script>
// 引入mixin
import { mixins } from "@/mixin/index";
export default {
name: 'mixin-1',
mixins: [mixins], //使用混入(mixin)
created(){
console.log("组件调用minxi数据",this.msg);
},
mounted(){
console.log("我是组件的mounted生命周期函数")
}
}
</script>
效果如下:
通过代码和效果我们可以得出以下几点:
- mixin中的生命周期函数会和组件的生命周期函数一起合并执行。
- mixin中的data数据在组件中也可以使用。
- mixin中的方法在组件内部可以直接调用。
- 生命周期函数合并后执行顺序:先执行mixin中的,后执行组件的。
注意:多组件引入mixin,一个组件改变了mixin中的数据另一个组件引入的mixin不受影响!!!
2.3 全局混入
修改main.js
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import { mixins } from "@/mixin/index";
Vue.config.productionTip = false
Vue.mixin(mixins);
new Vue({
render: h => h(App)
}).$mount("#app")
index.vue中引入的mixin删掉
<template>
<div>
<el-button @click="clickMiXin">测试</el-button>
</div>
</template>
<script>
export default {
name: 'mixin',
created(){
console.log("组件调用minxi数据",this.msg);
},
mounted(){
console.log("我是组件的mounted生命周期函数")
},
methods: {
}
}
</script>
效果如下:
注意:混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
三:选项合并
- 当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
- 比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
3.1 生命周期函数冲突
- 确切来说,这种不算冲突,因为生命周期函数的名称都是固定的。
- 默认的合并策略如下,先执行mixin中生命周期函数中的代码,然后在执行组件内部的代码,上面的例子其实就很好的证明了。
3.2 data数据冲突
当mixin中的data数据与组件中的data数据冲突时,组件中的data数据会覆盖mixin中数据
//创建一个mixin
var mixin = {
data: function () {
return {
msg: "我是Mixin中的msg",
}
}
}
new Vue({
mixins: [mixin], //引入mixin
data: function () {
return {
msg: '我是Index中的msg',
}
},
created: function () {
console.log(this.$data)
// => { msg: "我是Index中的msg"}
}
})
可以看到最终打印的msg是组件中msg的值,其它没有冲突的数据自然合并了。
3.3 方法冲突
这种冲突很容易遇到,毕竟大家命名方法的名字很容易一样
//创建一个mixin
var mixin = {
methods: {
clickMiXin() {
console.log("我是Mixin中的事件");
},
}
}
new Vue({
mixins: [mixin], //引入mixin
mounted(){
this.clickMiXin(); // => "我是Index中的事件"
},
methods: {
clickMiXin() {
console.log("我是Index中的事件");
},
}
})
上段代码中mixin和组件中都有clickMiXin方法,但是最终在组件中调用时,实际调用的是组件中的clickMiXin方法。
四:mixin的优缺点
4.1优点
- 提高代码复用性
- 无需传递状态
- 维护方便,只需要修改一个地方即可
4.1缺点
- 命名冲突
- 滥用的话后期很难维护
- 不好追溯源,排查问题稍显麻烦
- 不能轻易的重复代码
总结:
mixin给我们提供了方便的同时也给我们带来了灾难,所以有很多时候不建议滥用它,但是在有些场景下使用它又是非常合适的,这就得根据自己来取舍了。所以在很多时候我们需要考虑用公共组件还是使用mixin。