Vue 混入

在Vue 3中,混入(Mixin)是一种将可重用功能和逻辑添加到组件中的方式。混入可以包含组件选项,如datamethodscreated等,这样您可以在多个组件中重复使用相同的逻辑,而不必重复编写代码。混入提供了一种模块化的方式来组织和复用组件功能。

混入允许您将共享的逻辑封装到一个混入对象中,然后将混入对象应用到一个或多个组件中。这使得在不同的组件中共享通用功能变得更容易。混入对象中的选项将会被合并到组件的选项中。

mixins

以下是一个简单的混入示例:

1
2
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>',
};

// 创建 Vue 应用
const app = Vue.createApp(myComponent);
app.mount('#app');

点击Show Message按钮后则会输出如下结果

1
hello from myMinx

在上面的示例中,myMixin是一个混入对象,包含了datamethods选项。然后,我们创建一个myComponent组件,并将myMixin混入应用到该组件中。这使得messageshowMessage方法在myComponent中可用。

需要注意的是,混入可以包含任何选项,包括datamethodscomputedwatch等,但当多个混入对象具有相同的选项时,Vue 将会以一定的策略进行合并。这些策略可能会导致一些潜在的命名冲突,因此在使用混入时需要小心谨慎。通常,建议给混入的数据和方法命名时使用唯一的前缀或命名空间,以避免命名冲突。

选项合并

当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

数据对象合并

数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。

1
2
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 应用
Vue.createApp(MyComponent).mount('#app');
</script>
</body>
</html>

钩子函数合并

同名钩子函数将合并为一个数组,因此都将被调用。另外,mixin 对象的钩子将在组件自身钩子之前调用。

1
2
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 应用
Vue.createApp(MyComponent).mount('#app');
</script>
</body>
</html>

执行结果

1
2
mixin 对象的钩子被调用
组件的钩子被调用

函数合并

值为对象的选项,例如 methods、componentsdirectives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

1
2
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>

执行结果

1
2
3
foo
bar
form self

全局混入

全局混入可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。

1
2
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!'
})

// 为自定义的选项 'myOption' 注入一个处理器。
app.mixin({
created() {
const myOption = this.$options.myOption
if (myOption) {
document.write(myOption)
}
}
})

app.mount('#app') // => "hello!"
</script>
</body>
</html>

代码解析

  • 上面代码定义一个名为 myOption 的自定义选项,并将其设置为 'hello!'
    然后,通过以下代码段,使用全局混入 (app.mixin) 注入一个处理器,该处理器在每个组件实例的 created 钩子中检查 myOption 并在文档中打印它:

  • 当你调用 app.mount('#app') 时,Vue 应用实例会根据自定义选项 myOption 的值 'hello!' 执行全局混入中的 created 钩子,然后在页面上输出 "hello!"

参考资料