1
写文章不容易,点个赞呗兄弟
专注 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');
}

公众号


神仙朱
235 声望105 粉丝

不会认输