Vue源码学习(二)——生命周期
官网对生命周期给出了一个比较完成的流程图,如下所示:
从图中我们可以看到我们的Vue创建的过程要经过以下的钩子函数:
beforeCreate => created => beforeMount => mounted => beforeUpdate => updated => beforeDestroy => destroyed
那么我们就从源码的角度来看一看吧,当我们new Vue的时候,会执行_init函数
function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) }
init函数如下
export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { .... 以下就是进行了生命周期 vm._self = vm // 首先进行初始化生命周期的参数 initLifecycle(vm) // 在初始化事件 initEvents(vm) // 初始化render initRender(vm) // 开始调用beforeCreate钩子函数,和图中的流程图一样 callHook(vm, 'beforeCreate') // 之后开始初始化变量等一些数据 initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props // 开始调用created钩子函数 callHook(vm, 'created') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`vue ${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } }
以上init函数我们已经看到了beforeCreate和created,那么callHook是怎么调用的钩子函数呢?
export function callHook (vm: Component, hook: string) { // #7573 disable dep collection when invoking lifecycle hooks pushTarget() // 从$options里拿到钩子函数 const handlers = vm.$options[hook] if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { try { // 然后再调用 handlers[i].call(vm) } catch (e) { handleError(e, vm, `${hook} hook`) } } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } popTarget() }
这边就会有几个问题:
从vm.$options[hook]中取钩子函数,那个这个钩子函数是哪来来的? 为了拿到的钩子函数是个数组?我们平时使用不都是只是写个函数吗?
我们可以看到在$options是在下面_init中进行合并的
Vue.prototype._init = function(){ ... vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) ... } export const LIFECYCLE_HOOKS = [ 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated', 'errorCaptured' ]
我们可以看到钩子函数一开始就已经在vue内部已经定义好了,并且还有几个钩子函数不是实话化实例的使用执行的。而是对keep-alive组件配合使用的activated,deactivated。以及错误抛出钩子函数errorCaptured
然后再根据这些内部定义的钩子函数和传入的参数进行合并
那么为什么钩子函数是数组呢?这个其实很简单是因为vue内部也需要执行一些函数,顾把函数也放到钩子函数里。所以需要数组遍历。
所以这些所谓的钩子函数就是一个回调函数。
其余几个钩子函数也是在需要调用的时候使用callHook(vm, 'xxx')来执行
如果对您有帮助请点个赞,谢谢!
相关推荐
源码zanqunet 2020-10-28
anchongnanzi 2020-09-21
CRMCRMCRMDS 2020-08-12
Cricket 2020-07-27
yuzhu 2020-11-16
85477104 2020-11-17
KANSYOUKYOU 2020-11-16
sjcheck 2020-11-03
怪我瞎 2020-10-28
gloria0 2020-10-26
王军强 2020-10-21
学习web前端 2020-09-28
QiaoranC 2020-09-25
安卓猴 2020-09-12
Macuroon 2020-09-11
kiven 2020-09-11
LittleCoder 2020-09-11
Cheetahcubs 2020-09-13
小焊猪web前端 2020-09-10