假设一个项目,首页不需要登录就可以直接进入,但是在首页中有各种其他的模块,这些模块中,有些需要登录权限,而有些则不需要登录权限,所以在进入这些模块的时候,我们都要判断当前的登录状态,那么我们应该怎么组织这一部分代码呢?
在每一个需要登录状态的组件内,进行单独判断?
如果需要判断登录状态的模块比较少,也就是单独的组件很少,其实也无所谓,但是如果有10个、8个的模块需要判断登录状态呢?每个组件内部,判断一次?虽然代码都一样,也就是合并复制粘贴一下,但是,这是不是一种浪费,这时,就是mixins混入大展身手的时候了。
vue官方文档上说:
混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
单独定义一个mixin的文件,使用ES6模块方式,将其定义成一个完整的模块。假设文件名为mixin.js。
export default {
data() {
return {
msg: "这现在都可以这么玩了么?"
}
},
mounted() {
let loginState = window.localStorage.getItem("loginState");
console.log(loginState)
// 依赖loginState的结果进行不同的逻辑操作,或者路由跳转
}
}
这就是共用代码部分的mixin即可:
import mixin from "./mixin"
export default {
mixins: [mixin],
// 组件内其他逻辑操作代码
data(){
return {}
},
methods:{},
mounted(){}
...
}
如果还有其他需要混入的部分,用相同的方法引入即可,然后将引入的对象添加到mixins这个属性值的数组里面,数组的先后顺序决定了他们的执行顺序,比如都有mounted这个方法的话,就按mixins数组的先后顺序执行,最后才执行组件内部的mounted。
当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。 比如,数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。 值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。
就是说methods, components 和 directives这些个属性当中,如果有与mixin中对象的键名冲突了,那使用的是组件内部的键值。
export default {
data() {
return {
msg: "这现在都可以这么玩了么?"
}
},
methods: {
whyClick() {
console.log("why dispatch click, what would you like todo?")
}
},
mounted() {
let loginState = window.localStorage.getItem("loginState");
console.log(loginState)
// 依赖loginState的结果进行不同的逻辑操作,或者路由跳转
}
}
而同时,在引入该mixin的组件内部的methods中,也有whyClick这一方法
export default {
mixins: [mixin],
data (){
return {
// msg: "我就想看看这个mixin当中的this指向哪里?"
}
},
methods:{
whyClick(){
console.log("I just click, and test it, not OK ?")
}
},
...
}
此时,在组件中
<button @click="whyClick">whyClick, don't you kow?</button>
那么只会执行组件内部的whyClick方法,而不会执行mixin中的whyClick。
mixin不仅可以组件内局部混入,也可以全局混入。
Vue.mixin({
...
})
在这里需要提示注意的一点是:全局混入,即Vue.mixin({})需要写在new Vue({})之前,包括Vue.filter(), Vue.directive()也是如此,就是说所有全局定义的,需要在vue实例构造之前定义。
vue为我们定义了一整套选项合并的策略,但是总有一些特殊需求,需要一些特殊的合并策略,vue同时提供了自定义选项合并策略。
自定义选项将使用默认策略,即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并,可以向 Vue.config.optionMergeStrategies 添加一个函数:
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
// return mergedVal
}
更多复杂的合并策略可以翻看其官方文档自定义选项合并策略。