本章主要解释Vue中mixin的原理
全局方法mixin
import {mergeOptions} from './utils'
export function initGlobalAPI(Vue) {
// 静态方法
Vue.options = {}
Vue.mixin = function (mixin) {
// 我们期望将用户的选项和 全局的options进行合并 '
this.options = mergeOptions(this.options, mixin);
return this;
}
}
核心方法meageOptions
const strats = {};
const LIFECYCLE = [
'beforeCreate',
'created'
]
LIFECYCLE.forEach(hook => {
strats[hook] = function (p, c) {
// {} {created:function(){}} => {created:[fn]}
// {created:[fn]} {created:function(){}} => {created:[fn,fn]}
if (c) { // 如果儿子有 父亲有 让父亲和儿子拼在一起
if (p) {
return p.concat(c);
} else {
return [c]; // 儿子有父亲没有 ,则将儿子包装成数组
}
} else {
return p; // 如果儿子没有则用父亲即可
}
}
})
export function mergeOptions(parent, child) {
const options = {};
for (let key in parent) { // 循环老的 {}
mergeField(key);
}
for (let key in child) { // 循环老的 {a:1}
if (!parent.hasOwnProperty(key)) {
mergeField(key);
}
}
function mergeField(key) {
// 策略模式 用策略模式减少if /else
if (strats[key]) {
options[key] = strats[key](parent[key], child[key])
} else {
// 如果不在策略中则以儿子为主
options[key] = child[key] || parent[key]; // 优先采用儿子,在采用父亲
}
}
return options;
}
初始化时调用钩子函数
Vue.prototype._init = function (options) { // 用于初始化操作
// vue vm.$options 就是获取用户的配置
const vm = this;
vm.$options = mergeOptions(this.constructor.options,options); // 将用户的选项挂载到实例上
callHook(vm,'beforeCreate'); // 内部调用的是beforeCreate 写错了就不执行了
// 初始化状态
initState(vm);
callHook(vm,'created');
}
调用函数
export function callHook(vm,hook){ // 调用钩子函数
const handlers = vm.$options[hook];
if(handlers){
handlers.forEach(handler=>handler.call(vm))
}
}
这样自己的函数就会在对应的生命周期中执行,同时自己的属性也会赋给option。