mixin的概念
官网
:混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
简单描述
:提取公共逻辑,降低组件代码冗余程度,哪个组件需要用到mixin的逻辑,就单独去引入对应的mixin文件即可
注意:
mixin是一个对象
定义一个mixin
我的项目是v2-advanced-usage
// src目录下创建一个mixins文件夹并新增一个js文件
// 路径:v2-advanced-usage/src/mixins/getNameMixin.js
// 定义一个名为getNameMixin混入对象
export const getNameMixin = {
components: {},
data() {
return {
message: 'this is getNameMixin msg',
foo: 'abc'
};
},
};
- mixin(混入)有Vue完整的生命周期和数据状态
- 可以在mixin的js文件中定义公共的数据、公共的方法、钩子函数等
使用mixin
<!--在App.vue文件中引入mixin-->
<!--此时页面显示的信息是getNameMixin中的数据:this is getNameMixin msg-->
<template>
<div id="app">
<h4>
<span>This data comes from getNameMixin file:</span>
<span style="color: blueviolet">{{ message }}</span>
</h4>
</div>
</template>
<script>
import { getNameMixin } from "./mixins/getNameMixin";
export default {
name: "App",
mixins: [getNameMixin],
};
</script>
mixin和组件的优先级
在App.vue中增加自身的methods方法和data状态
// 修改App.vue文件
<template>
<div id="app">
<h4>
<span>This data comes from getNameMixin file:</span>
<span style="color: blueviolet">{{ name }}</span>
</h4>
</div>
</template>
<script>
import { getNameMixin } from "./mixins/getNameMixin";
export default {
name: "App",
mixins: [getNameMixin],
data: function () {
return {
message: 'this is component msg',
bar: 'def'
}
},
created: function () {
console.log(this.message)
// => "this is component msg"
}
};
</script>
/**
* 此时页面显示的是组件的数据:'this is component msg',而不是mixins里面的'this is getNameMixin msg'
* created钩子函数打印的是组件内的数据"this is component msg"
*/
总结:
1. 当组件和混入(mixin)对象含有同名数据时,这些数据会进行“合并”,并且组件优先级最高,非同名数据会放到一个对象里面
示例1:
// getNameMixin的message被组件内的message覆盖,mixinDemo的foo属性和组件内的bar属性放到一个对象内
// getNameMixin.js内的代码
export const getNameMixin = {
data() {
return {
message: 'this is mixinDemo msg',
foo: 'abc'
}
}
}
// App.vue文件代码
<template>
<div id="app">
<h4>
<span>This data comes from getNameMixin file:</span>
<span style="color: blueviolet">{{ message }}</span>
</h4>
</div>
</template>
<script>
import { getNameMixin } from "./mixins/getNameMixin";
export default {
name: "App",
mixins: [getNameMixin],
data: function () {
return {
message: 'this is component msg',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "this is component msg", foo: "abc", bar: "def" }
}
};
</script>
2. 当组件和混入(mixin)对象含有同名生命周期钩子函数时,这些生命周期钩子函数会“合并”为一个数组,并且混入对象内的函数优先调用,组件自身函数后调用
示例2:
// 同名生命周期钩子函数,优先执行mixinDemo中的钩子函数,后执行组件内的钩子函数
var mixinDemo = {
created: function () {
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins: [mixinDemo],
created: function () {
console.log('组件钩子被调用')
}
})
// => 输出:"混入对象的钩子被调用"(优先触发了)
// => 输出:"组件钩子被调用"
3. 组件和混入(mixin)对象中的methods、components 和 directives,将被合并为同一个对象,如果有同名的冲突,以组件自身为准
示例3:
// conflicting为同名的methods函数,mixinDemo内的不再调用,只会触发组件内的conflicting
var mixinDemo = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixinDemo],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
mixin也可以通过Vue.mixin的方式混入到全局中,使用时需要格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例,这是非常危险的行为
mixin的缺点:
- 命名冲突,data、生命周期、methods、components、directives等都会出现冲突现象
- 依赖不透明,不利于问题溯源,因为mixin 和使用它的组件之间没有层次关系
- 全局注册的mixin,会影响到整个实例下的所有组件,在使用过程中,容易出现察觉不到的问题
结论
:不建议使用太多的mixin,项目开发时,可以使用函数式编程范式,提取公共函数的方式来处理公共问题,业务逻辑可以抽离独立组件的方式来处理