返回 导航

Vue.js

hangge.com

Vue.js - Mixin使用详解(通过混入实现代码复用)

作者:hangge | 2026-04-18 09:27
    当使用组件化的方式开发 Vue.js 的应用程序时,组件和组件之间有时会存在相同的代码逻辑,这时我们希望对相同的代码逻辑进行抽取。MixinVue 提供的一种代码复用机制,你可以把一组组件选项(datamethods、生命周期钩子、computed 等)封装成一个可复用的对象,然后在多个组件中 mix 进来。
    MixinVue 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 的文件,其内部封装了一个名为 demoMixinMixin 对象,该对象中定义了 datamethods 和 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 对象和组件对象中的生命周期钩子函数会被合并到数组中,都会被调用。 
  • 处理值为对象的选项。如 methodscomponentsdirectives 选项,将被合并为同一个对象。例如,Mixin 对象和组件对象中都有 methods 选项,并且都定义了方法,那么它们都会生效。但是如果对象的 key 相同,那么会取组件对象的键值对。 

(2)下面修改修改 App.vue 组件,演示一下 demoMixin 对象和组件对象中 datamethodscreated 选项出现冲突的情况。 
  • 如果 data 中的 message 变量和 demoMixin 对象中定义的 message 变量发生冲突,那么会使用该组件的 message。 
  • 如果 methodsfoo 方法和 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)

回到顶部