写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧 研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧
【Vue原理】生命周期 - 源码版
好的!今天探索Vue的生命周期,鉴于生命周期这个东西很简单,所以直接写源码版了
简单到什么程度呢,就是直接执行你的 created 什么的,只是分在什么时候执行而已
但是!我们仍然要分两个问题,理清思路方便记忆
1、生命钩子怎么触发
2、生命钩子在什么时候触发
钩子怎么触发
首先,我设置了下面的例子
那么 el 和 created 就是你传入 Vue 的自定义选项啦
1、把所有同类钩子先合并成数组,然后存放在 vm.$options
这个点跟 mixins 有关,可以看这篇下对钩子的合并处理
【Vue原理】Mixins - 源码版
合并,主要是为了把全局设置的钩子和 组件自定义的钩子合并起来,就算你没有全局钩子,也要存在数组里面,比如 created 是下面
vm.$options={
created:[fn,fn,fn...]
}
2、初始化设置一些标志位,表明是否已经完成某种钩子
function initLifecycle(vm) {
vm._isMounted = false;
vm._isDestroyed = false;
vm._isBeingDestroyed = false;
}
这个函数会在 beforeCreated 钩子触发前调用,在 Vue.prototype._init 中,下个问题源码有显示。其中的标志位什么时候设置呢,是在相应的钩子触发之后,具体看下面源码
3怎么执行钩子呢
没错,就是下面这个函数
function callHook(vm, hook) {
// 是自己传入的 created 等回调
var handlers = vm.$options[hook];
if (handlers) {
for (var i = 0,j = handlers.length; i < j; i++) {
handlers[i].call(vm);
}
}
}
那是怎么用呢?
比如触发 created 就会这么调用
callHook(vm,'created')
很简单4不4,直接拿到钩子,然后遍历执行,绑定上下文对象。
为什么是数组?上面已经说过啦,一个实例通过mixins可能有很多个相同钩子,所以合并成的数组
钩子什么时候触发
要说讲解钩子在什么时候触发把,好像也没什么讲的,Vue文档都说清楚了,但是很显然,所以我们直接以源码的形式给出来
下面就说了几个钩子,有几个感觉不太常用,就不列出来了
function Vue(opt){
this._init(opt)
}
Vue.prototype._init(opt){
... 合并选项
... 设置初始值 ,事件 等数据
initLifecycle(vm)
callHook(vm, 'beforeCreate');
... 初始化选项等数据
callHook(vm, 'created');
...获取挂载的DOM 父节点
callHook(vm, 'beforeMount');
...解析模板成渲染函数,并执行渲染函数,生成DOM插入页面
vm._isMounted = true;
callHook(vm, 'mounted');
}
// 组件更新时会调用这个函数
Vue.prototype._update = function(
vnode, hydrating
) {
if (vm._isMounted) {
callHook(vm, 'beforeUpdate');
}
...重新调用渲染函数,对比旧节点和新节点,得到最小差异,然后只更新这部分页面
callHook(vm, 'updated');
}
// 节点被移除时会调用这个函数
Vue.prototype.$destroy = function() {
callHook(vm, 'beforeDestroy');
vm._isBeingDestroyed = true;
...实例被消除,移除所有 watcher
vm._isDestroyed = true;
...DOM被移除
callHook(vm, 'destroyed');
}