一、介绍
官方定义:
mixin(混入),提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods、created、computed等等。
混入(Mixin) 是一种代码复用的模式。它的主要目的是将一个对象的功能“混入”到另一个对象中,而不是通过继承。这种模式通常被用来在多个类之间共享功能,而无需使用复杂的继承层次。
(Mixin
是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin
类的方法而不必成为其子类;Mixin
类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂)
在Vue中我们可以局部混入跟全局混入
二、局部混入
定义一个 mixins.js 文件,此文件中可以混入Vue中所有的设置项,methods、computed、watch、data、生命周期函数等都可以。
// mixin.js
export const myMixin = {
methods: {
sharedMethod() {
console.log('This method is shared between components.');
}
}
};
// MyComponent.vue
<template>
<div>
<button @click="sharedMethod">Click me</button>
</div>
</template>
<script>
import { myMixin } from './mixin.js';
export default {
mixins: [myMixin],
// 组件自己的选项...
};
</script>
三、全局混入
全局混入表示混入到Vue对象中,Vue下的所有组件都会使用混入的方法,一定要注意,是所有的组件,所以,在使用全局混入的时候要确保所有的组件都会使用到。
如果在使用混入的过程中出现冲突,除生命周期钩子外,其余的都以本组件中的为主,混入的不生效;生命周期钩子产生冲突是先执行混入的声明周期钩子,再执行本组件的生命周期钩子。
//main.js文件
import {mixin1, mixin2} from "../mixins.js"
Vue.mixin(mixin1)
Vue.mixin(mixin2)
//如果不想创建单独的类,也可以直接写一个配置对象
Vue.mixin({
created: function () {
console.log("全局混入")
}
})
PS:全局混入常用于插件的编写,使用全局混入需要特别注意,因为它会影响到每一个组件实例(包括第三方组件)
四、使用场景
在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些功能相同或者相似的代码(造成代码冗余),这时可以通过Vue的mixin功能将相同或者相似的代码抽取出来。
举个例子
定义一个modal弹窗组件,内部通过isShowing来控制显示
const Modal = {
template: '#modal',
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
}
}
定义一个tooltip提示框,内部通过isShowing来控制显示
const Tooltip = {
template: '#tooltip',
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
}
}
通过观察上面两个组件,发现两者的逻辑是相同,代码控制显示也是相同的,这时候mixin就派上用场了
首先抽出共同代码,编写一个mixin
const toggle = {
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
}
}
两个组件在使用上,只需要引入mixin
const Modal = {
template: '#modal',
mixins: [toggle]
};
const Tooltip = {
template: '#tooltip',
mixins: [toggle]
}
五、 思考与应用
把多个组件共有的配置提取成一个混入对象,然后通过局部混入或者全局混入,以达到共用配置的目的,这就是mixin。
将组件的公共逻辑或者配置(包括data
,方法
,生命周期
,甚至props
等)提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗余度,也可以让后期维护起来更加容易,改一处即可,不用到处去每个组件内修改配置
注意:提取的是逻辑或配置,而不是HTML
代码和CSS
代码。也就是说,mixin
就是组件中的组件(那么组件与组件之间还有重复部分,比如逻辑业务的复用,我们还可以使用Mixin
在抽离一遍),Vue
组件化让我们的代码复用性更高
创建一个popButton_mixin.js 文件,创建一个对象,然后暴露出去,如下所示
export const popButtonMixin = {
data() {
return {
name: "大壮",
age: 18
}
},
created() {
console.log("混入生命周期开始执行");
},
mounted() {
console.log("我是混入");
},
methods: {
//这里需要注意如果被混入组件data里有重名name会覆盖当前的name:“大壮”,没有同名属性则默认使用此值
handleButton() {
alert(this.name);
},
handleMounted() {
console.log("加载方法");
}
}
}
然后在组件ButtonA.vue 使用处引入即可:
<template>
<div>
<h1>ButtonA</h1>
<el-button type="primary" @click="handleClick">A按钮</el-button>
</div>
</template>
<script>
import { popButtonMixin } from "./popButton_mixin";
export default {
name: "ButtonA",
data() {
return {
name: "ButtonA",
};
},
mixins: [popButtonMixin],
methods: {
handleClick() {
this.handleButton();
},
},
};
</script>
<style>
</style>
5.1、几个重要的疑问
mixin
中的生命周期函数会和组件的生命周期一起合并执行;mixin
中的data
数据在组件中可以使用;mixin
中的方法在组件内部可以直接调用;- 生命周期函数合并后执行顺序:先执行
mixin
中的,然后执行组件的; mounted
不会合并,都会加载一遍;- 不同组件中的
mixin
是相互独立的,改变一个组件中mixin
中的数据,另一个引用了mixin
的组件不会受影响;
data数据冲突
当
mixin
中的data
数据与组件中的data
数据冲突时,组件中的data
数据会覆盖mixin
中的数据若是没有相同的话,会进行数据的合并
方法名冲突
在同一个项目里,起相同的名称,是很容易遇到的,如果
mixin
中的方法名与引入mixin
中组件的方法名一致时,那么以当前组件为准
下面将进行验证不同组件中的mixin
是相互独立的:
mixin中的data
data() {
return {
name: "大壮",
age: 18
}
},
在组件ButtonA中修改mixin中age为38
methods: {
handleClick() {
this.age = 38;
this.handleButton();
},
},
在组件ButtonB中修改mixin中打印age依然是18