# mixin
# 简述
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。mixin API 用于解决组件中重复逻辑代码的问题。
// 定义一个混入对象
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// 定义一个使用混入对象的组件
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"
在业务代码中使用 mixin 需要慎重,尤其是全局混入。因为 mixin 会导致数据来源不明确,并且在声明时可能会导致命名冲突,当命名冲突时,会以组件内部的数据优先。
# 原理
mixin 的实现原理非常简单,其实就是在初始化 Vue 实例时,将 mixin 传入的 options 选项和 Vue 的 options 选项合并即可。
Vue.mixin = function (mixin) {
// 合并原有的钩子和传进来的钩子
this.options = mergeOptions(this.options, mixin);
return this;
};
mergeOptions:
// 合并两个对象,合并mixin时用到
function mergeOptions(parent, child) {
var options = {};
// 合并老的属性,其实就是将{create:fn()} => {create:[fn]},数组化
for (var key in parent) {
mergeField(key);
}
for (var _key in child) {
if (!parent.hasOwnProperty(_key)) {
// 不合并已经合并过的属性
mergeField(_key);
}
}
// 合并options,优先后传入的mixin
function mergeField(key) {
if (strats[key]) {
// 有相应的策略,按照策略合并
options[key] = strats[key](parent[key], child[key]);
} else {
// 策略模式,针对不同的属性采取不同的合并策略
options[key] = child[key] || parent[key];
}
}
return options;
}