Vue.js - Mixin使用详解(通过混入实现代码复用)
作者:hangge | 2026-04-18 09:27
当使用组件化的方式开发 Vue.js 的应用程序时,组件和组件之间有时会存在相同的代码逻辑,这时我们希望对相同的代码逻辑进行抽取。Mixin 是 Vue 提供的一种代码复用机制,你可以把一组组件选项(data、methods、生命周期钩子、computed 等)封装成一个可复用的对象,然后在多个组件中 mix 进来。
(2)接着我们在 App.vue 中从 demoMixin.js 文件中导入 demoMixin 对象,接着将 demoMixin 对象放到一个数组中,并赋值给 mixins 属性。这样做的目的是将 demoMixin 对象的选项混入 App.vue 组件中,最终可以在 template 中直接使用 demoMixin 对象定义的选项。
(3)运行结果如下,可以看到 App.vue 组件能正常使用混入的代码逻辑。
(3)最后运行效果如下下图所示:
(3)运行效果如下,通过控制台输出可以发现会先执行全局混入的 created 钩子函数, 接着执行 demoMixin 对象定义的 created 钩子函数,最后执行 App.vue 组件定义的 created 钩子函数。
Mixin 在 Vue 2 项目中非常常见,但在 Vue 3 中因为 Composition API 的出现,mixins 的使用逐渐被可组合函数(composables)替代。下面将通过样例演示 Mixin 的使用。
1,Mixin 介绍
(1)Mixin 具有如下特点:
- Mixin 提供了一种非常灵活的方式来分发 Vue.js 组件中可复用的功能。
- 一个 Mixin 对象可以包含任何组件的选项(Options API)。
- 当组件使用 Mixin 对象时,所有 Mixin 对象的选项都将被混入该组件本身的选项中
(2)尽管 Mixin 可以对组件代码逻辑进行抽取和复用,但它存在如下缺陷:
- Mixin 容易发生冲突。由于每个 Mixin 对象的属性都被合并到同一个组件中,为了避免属性名冲突,我们需要了解其他 Mixin 对象的属性命名特征。
- Mixin 的可复用性是有限的。例如,我们无法向 Mixin 传递任何参数来改变它的逻辑,这降低了它在抽取逻辑方面的灵活性。
2,基本用法
(1)首先我们创建一个名为 demoMixins.js 的文件,其内部封装了一个名为 demoMixin 的 Mixin 对象,该对象中定义了 data、methods 和 created 选项。
// 定义个混合对象
export const demoMixin = {
data() {
return {
message: "Hello demo",
};
},
methods: {
foo() {
console.log("demo mixin foo");
},
},
created() {
console.log("执行了demo mixin created");
},
};
(2)接着我们在 App.vue 中从 demoMixin.js 文件中导入 demoMixin 对象,接着将 demoMixin 对象放到一个数组中,并赋值给 mixins 属性。这样做的目的是将 demoMixin 对象的选项混入 App.vue 组件中,最终可以在 template 中直接使用 demoMixin 对象定义的选项。
<template>
<div>
<h2>{{ message }}</h2>
<button @click="foo">单击调用demoMixin定义的foo方法</button>
</div>
</template>
<script>
import { demoMixin } from './demoMixin';
export default {
mixins: [demoMixin],
}
</script>
(3)运行结果如下,可以看到 App.vue 组件能正常使用混入的代码逻辑。

3,Mixin 的合并规则
(1)如果 Mixin 对象中的选项和组件对象中的选项发生了冲突,那么 Vue.js 会分成三种情况来处理。
- 处理 data 函数返回值对象。默认情况下,Mixin 对象中 data 选项的返回值和组件对象中 data 选项的返回值会进行合并。如果它们的 data 选项返回值对象的属性发生了冲突,那么会保留组件对象自身的数据。
- 处理生命周期钩子函数。Mixin 对象和组件对象中的生命周期钩子函数会被合并到数组中,都会被调用。
- 处理值为对象的选项。如 methods、components 和 directives 选项,将被合并为同一个对象。例如,Mixin 对象和组件对象中都有 methods 选项,并且都定义了方法,那么它们都会生效。但是如果对象的 key 相同,那么会取组件对象的键值对。
(2)下面修改修改 App.vue 组件,演示一下 demoMixin 对象和组件对象中 data、methods 和 created 选项出现冲突的情况。
- 如果 data 中的 message 变量和 demoMixin 对象中定义的 message 变量发生冲突,那么会使用该组件的 message。
- 如果 methods 中 foo 方法和 demoMixin 对象中定义的 foo 方法发生冲突,那么会使用该组件定义的 foo 方法。
- 如果组件生命周期的钩子函数和 demoMixin 对象中定义的生命周期的钩子函数 created 重复,那么会将两个函数合并到数组中,然后遍历该数组逐一调用。
<template>
<div>
<h2>{{ message }}</h2>
<button @click="foo">单击调用demoMixin定义的foo方法</button>
</div>
</template>
<script>
import { demoMixin } from './demoMixin';
export default {
mixins: [demoMixin],
data() {
return {
// 1.message变量和demoMixin对象中定义的message冲突了。那么会使用该组件的message
message: "Hello App",
title: "Hello World"
}
},
methods: {
// 2.foo 方法和demoMixin对象中定义的foo冲突了。那么使用该组件的foo方法
foo() {
console.log("app foo");
},
bar() {
console.log("bar function");
}
},
// 3.生命周期的钩子函数如何和混合中的重复了。那么会被合并到数组中,都会被调用。
created() {
console.log("App created 执行");
}
}
</script>
(3)最后运行效果如下下图所示:

4,全局混入 Mixin
(1)如果所有组件都需要某些选项,那么可以使用全局 Mixin。全局 Mixin 可以使用 app.mixin 方法进行注册。一旦注册,全局混入的选项将被混入每个组件中。
(2)修改 main.js 文件,代码如下所示:
import Vue from 'vue';
import App from './App.vue';
Vue.mixin({
created() {
// 小心:会在每个组件创建时执行
// 适合做极少数全局行为,例如开发环境下统一打点或调试输出
if (process.env.NODE_ENV === 'development') {
console.log("global mixin created");
}
}
});
new Vue({ render: h => h(App) }).$mount('#app');
(3)运行效果如下,通过控制台输出可以发现会先执行全局混入的 created 钩子函数, 接着执行 demoMixin 对象定义的 created 钩子函数,最后执行 App.vue 组件定义的 created 钩子函数。

全部评论(0)