前言
相信vue生命周期的几个钩子大家都很清楚,那它具体是怎么实现的呢?
在讲生命周期原理之前,我们还要先讲一下vue.mixin这个和生命周期有关的api。
mixin
简介
vue官方文档是这么介绍的
全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用。
通俗点讲,就是对Vue构造函数做一些混入操作,影响每个vue实例。
原理
通过mergeOptions 将各个Vue.mixin的 options 合并到Vue.options上
import {mergeOptions} from '../util/index.js'
export function initGlobalAPI(Vue){
Vue.options = {};
Vue.mixin = function (mixin) {
this.options = mergeOptions(this.options,mixin);
return this;
}
}
采用策略模式,不同options(比如data、method、lifeCycleHooks)对应不同合并策略。
let lifeCycleHooks = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
]
let strats = {}; // 存放各种策略
// {} {beforeCreate:Fn} => {beforeCreate:[fn]}
// {beforeCreate:[fn]} {beforeCreate:fn} => {beforeCreate:[fn,fn]}
function mergeHook(parentVal, childVal) {
if (childVal) {
if (parentVal) {
return parentVal.concat(childVal); // 后续
} else {
return [childVal]; // 第一次
}
} else {
return parentVal
}
}
lifeCycleHooks.forEach(hook => {
strats[hook] = mergeHook
});
export function mergeOptions(parent, child) {
const options = {}; // 合并后的结果
for (let key in parent) {
mergeField(key);
}
for (let key in child) {
if (parent.hasOwnProperty(key)) {
continue;
}
mergeField(key);
}
function mergeField(key) {
let parentVal = parent[key];
let childVal = child[key];
// 策略模式
if (strats[key]) { // 如果有对应的策略就调用对应的策略即可
options[key] = strats[key](parentVal, childVal)
} else {
if (isObject(parentVal) && isObject(childVal)) {
options[key] = { ...parentVal, ...childVal }
} else {
options[key] = child[key] || parent[key];
}
}
}
return options
}
生命周期原理
1.合并生命周期
合并vm.$options 上和Vue.options,也是通过上述mergeOptions方法
Vue.prototype._init = function(options) {
//...
vm.$options = mergeOptions(vm.constructor.options, options);
}
2.调用生命周期
通过callHook找到实例的钩子,让钩子数组里的方法依次执行。
export function callHook(vm,hook){
let handlers = vm.$options[hook];
if(handlers){
for(let i =0; i < handlers.length;i++){
handlers[i].call(vm)
}
}
}
3.初始化流程中调用生命周期
在初始化流程中的不同阶段调用callhook
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = mergeOptions(vm.constructor.options,options);
// 初始化状态
callHook(vm,'beforeCreate');
initState(vm);
callHook(vm,'created');
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
}
上面是手写的简易版实现原理
我们再来看看源码😊
没错吧,源码就是通过callHook来实现vue的生命周期原理。
小结
vue的生命周期原理,就是将各个生命周期里的方法合并,存到数组里。在通过callhook,来调用各个生命周期里对应的方法。最后在初始化流程中的不同阶段调用对应的callhook。