混入(mixin)提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项(如data、methods、mounted等)。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
一、基本使用
1、定义一个混入(mixin)
2、在组件中使用
注意观察 Home 组件里面,并没有任何的生命周期钩子或者方法,但是打开页面之后查看控制台,却打印了内容,这就是混入对象中 created 钩子的 console.log() 。
现在,在Home组件加上mounted生命周期钩子
查看控制台打印信息:
非但没报错, 还打印出了混入对象中定义的hello方法,也验证了当前组件中合并了混入对象中定义的选项和方法。
二、选项合并
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
如下,我们在Home.vue中定义与混入对象中同名的选项
mixin.js
Home.vue
查看控制台打印信息:
此时,同名的created生命周期钩子进行了合并,合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。而 methods 中的 hello 方法因为冲突,在合并时保留组件中的hello,即优先当前组件的选项,因此打印的是 hello from Home!。
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
三、可复用性
开篇提过,混入对象可成为一个可复用功能,我们在另外的组件中引入已定义的混入对象,可实现同样的逻辑与功能。
如在另外一个组件About.vue使用该混入对象
查看控制台打印信息:
那么有个问题,如果很多个组件同时使用同一个混入对象,这时候都要重复一个步骤,就是先导入混入对象,然后再使用,类似如下
<script>
import myMixins from "../mixins";
export default {
mixins: [myMixins]
};
</script>
这样未免有点繁琐,且代码冗余,此时我们可以使用全局混入来优化这个问题。
四、全局混入
混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
在 main.js 中通过 Vue.mixin() 引入混入对象即可全局使用
效果与在每个组件中单独引入混入对象相同,这便是全局混入。
五、源码分析
export default function initMixin(Vue){
Vue.mixin = function (mixin) {
// 合并对象
this.options=mergeOptions(this.options,mixin)
};
}
};
// src/util/index.js
// 定义生命周期
export const LIFECYCLE_HOOKS = [
"beforeCreate",
"created",
"beforeMount",
"mounted",
"beforeUpdate",
"updated",
"beforeDestroy",
"destroyed",
];
// 合并策略
const strats = {};
// mixin核心方法
export function mergeOptions(parent, child) {
const options = {};
// 遍历父亲
for (let k in parent) {
mergeFiled(k);
}
// 父亲没有 儿子有
for (let k in child) {
if (!parent.hasOwnProperty(k)) {
mergeFiled(k);
}
}
//真正合并字段方法
function mergeFiled(k) {
if (strats[k]) {
options[k] = strats[k](parent[k], child[k]);
} else {
// 默认策略
options[k] = child[k] ? child[k] : parent[k];
}
}
return options;
}