在Vue 3中,混入(Mixin)是一种将可重用功能和逻辑添加到组件中的方式。混入可以包含组件选项,如data、methods、created等,这样您可以在多个组件中重复使用相同的逻辑,而不必重复编写代码。混入提供了一种模块化的方式来组织和复用组件功能。
混入允许您将共享的逻辑封装到一个混入对象中,然后将混入对象应用到一个或多个组件中。这使得在不同的组件中共享通用功能变得更容易。混入对象中的选项将会被合并到组件的选项中。
mixins
以下是一个简单的混入示例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | const myMixin = {
 data() {
 return {
 message: 'Hello from mixin!',
 };
 },
 methods: {
 showMessage() {
 console.log(this.message);
 },
 },
 };
 
 
 const myComponent = {
 mixins: [myMixin],
 template: '<div><button @click="showMessage">Show Message</button></div>',
 };
 
 
 const app = Vue.createApp(myComponent);
 app.mount('#app');
 
 | 
点击Show Message按钮后则会输出如下结果
在上面的示例中,myMixin是一个混入对象,包含了data和methods选项。然后,我们创建一个myComponent组件,并将myMixin混入应用到该组件中。这使得message和showMessage方法在myComponent中可用。
需要注意的是,混入可以包含任何选项,包括data、methods、computed、watch等,但当多个混入对象具有相同的选项时,Vue 将会以一定的策略进行合并。这些策略可能会导致一些潜在的命名冲突,因此在使用混入时需要小心谨慎。通常,建议给混入的数据和方法命名时使用唯一的前缀或命名空间,以避免命名冲突。
选项合并
当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。
数据对象合并
数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 | <!DOCTYPE html><html>
 <head>
 <meta charset="utf-8">
 <title>Vue 测试实例 - 混入</title>
 <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
 <div id = "app"></div>
 <script>
 
 const myMixins={
 data(){
 return{
 message:'hello from myMinx',
 }
 },
 methods: {
 changeMessage(){
 console.log(this.message)
 }
 }
 }
 
 
 const MyComponent={
 mixins:[myMixins],
 template: `<div><button @click="changeMessage">changeMessage</button></div>`,
 data(){
 return{
 message:'hello from MyComponent '
 }
 }
 }
 
 
 Vue.createApp(MyComponent).mount('#app');
 </script>
 </body>
 </html>
 
 | 
钩子函数合并
同名钩子函数将合并为一个数组,因此都将被调用。另外,mixin 对象的钩子将在组件自身钩子之前调用。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | <!DOCTYPE html><html>
 <head>
 <meta charset="utf-8">
 <title>Vue 测试实例 - 钩子函数混入</title>
 <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
 <div id = "app"></div>
 <script>
 
 const myMixins={
 created(){
 console.log('mixin 对象的钩子被调用');
 },
 }
 
 
 const MyComponent={
 mixins:[myMixins],
 created(){
 console.log('组件的钩子被调用');
 }
 }
 
 
 Vue.createApp(MyComponent).mount('#app');
 </script>
 </body>
 </html>
 
 | 
执行结果
函数合并
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 
 | <!DOCTYPE html><html>
 <head>
 <meta charset="utf-8">
 <title>Vue 测试实例 - 函数合并</title>
 <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
 <div id = "app"></div>
 <script>
 const myMixin = {
 methods: {
 foo() {
 console.log('foo')
 },
 conflicting() {
 console.log('from mixin')
 }
 }
 }
 
 const app = Vue.createApp({
 mixins: [myMixin],
 methods: {
 bar() {
 console.log('bar')
 },
 conflicting() {
 console.log('from self')
 }
 }
 })
 
 const vm = app.mount('#app')
 
 vm.foo()
 vm.bar()
 vm.conflicting()
 </script>
 </body>
 </html>
 
 | 
执行结果
全局混入
全局混入可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | <!DOCTYPE html><html>
 <head>
 <meta charset="utf-8">
 <title>Vue 测试实例 - 全局混入</title>
 <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
 <div id = "app"></div>
 <script type = "text/javascript">
 const app = Vue.createApp({
 myOption: 'hello!'
 })
 
 
 app.mixin({
 created() {
 const myOption = this.$options.myOption
 if (myOption) {
 document.write(myOption)
 }
 }
 })
 
 app.mount('#app')
 </script>
 </body>
 </html>
 
 | 
代码解析
- 上面代码定义一个名为 - myOption的自定义选项,并将其设置为- 'hello!'。
 然后,通过以下代码段,使用全局混入 (- app.mixin) 注入一个处理器,该处理器在每个组件实例的- created钩子中检查- myOption并在文档中打印它:
 
- 当你调用 - app.mount('#app')时,Vue 应用实例会根据自定义选项- myOption的值- 'hello!'执行全局混入中的- created钩子,然后在页面上输出- "hello!"。
 
参考资料