mixin与hooks对比

1,658 阅读2分钟

mixin与hooks对比

两者都是为了解决逻辑代码复用的问题

  • mixin 混入
    • Vue2.x 产物
  • hooks 钩子
    • Vue3.x 产物

本文阅读时间 5 分钟

mixin

遵循的原则

  • Vue 生命周期钩子函数,会直接合并,如created,mounted等,并且 Mixins 中钩子函数的执行要早于组件内
  • methods 同名方法会进行合并,但如果方法名冲突,组件内方法将覆盖 Mixins 中的方法
  • Mixins 方法和参数在组件间不共享
    • 即每一个 component 都有他独特的 mixins 作用域
    • 修改一个不会影响另一个

举个🌰

// test.js
export default {
    created() {
        console.log('这是从mix页面输出');
    },
    mounted() {
        console.log('这是从mix页面mounted输出');
    }
};

// app.vue
export default {
  name: "App",
  mixins: [test],
  created() {
       console.log('这是从APP页面输出');
  },
  mounted() {
      console.log('这是从APP页面mounted输出');
  }
};

// 输出结果
这是从mix页面输出
这是从APP页面输出
这是从mix页面mounted输出
这是从APP页面mounted输出

从上面可以印证第一点,mixin 中的生命周期钩子函数要早于组件的生命周期钩子函数。咱们再看下如果 mixin 中定义了相同的 变量 或 方法,Vue 又是如何处理的?

// test.js
export default {
    data() {
        return {
            message: 'mixin-message'
        };
    },
    methods: {
      mixinTest() {
          console.log('mixin');
      }
    }
};

// App.vue
export default {
  name: "App",
  mixins: [test],
  data() {
    return {};
  },
  methods: {
  },
};

// 模板 会正常显示 mixin 中的 变量 和 调用方法
<template>
  <div id="app">
    {{ message }}<button @click="mixinTest">按钮</button>
  </div>
</template>

// 修改 App.vue
// 修改之后 就变成了 component 中的变量和方法
export default {
  name: "App",
  mixins: [test, test2],
  data() {
    return {
        message: 'component-message'
    };
  },
  methods: {
    mixinTest() {
      console.log('component');
    },
  },
};

缺点

逻辑代码的复用,可以减少我们重复写代码。

但使用 mixin 最头痛的莫过于命名问题

  • 如果一段逻辑不能在多个组件之中进行复用,那么也就没有提取的必要,但恰恰是多个组件的复用就会有命名问题,我们知道混入规则中,
  • 如果值为对象的选项,命名冲突时组件内方法将会覆盖混入方法,这使得我们在多个组件复用时,编写代码更为困难,同时如果一旦改动 mixin 中的代码,那么引用并混入的所有组件都会受到影响,可谓牵一发而动全身。

hooks

对比 mixin 的使用方式

举个🌰

// src/hooks/useFoo.js
export function useFoo() {
    let message = '我是 useFoo 中的 message';

    function test() {
        console.log('useFoo 的 test');
    }
    return {
        message,
        test
    };
}

// App.vue
<script setup>
import { useFoo } from "./hooks/useFoo";
const { message: fooMessage, test } = useFoo();
</script>

<template>{{ fooMessage }}<button @click="test">按钮</button></template>
  • 在组件的 setup 函数中使用
    • const { message, test } = useFoo();
    • 自定义的 hooks 一定要是 use 开头!
  • 重名情况可以在组件中重新定义
    • const { message: fooMessage, test } = useFoo();
    • 形式 oldName : newName

hook 的方式解决了 mixin 的混入问题,并且语义也更友好!