官网对生命周期给出了一个比较完成的流程图,如下所示:

从图中我们可以看到我们的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')来执行

如果对您有帮助请点个赞,谢谢!

原文地址:https://segmentfault.com/a/1190000016906255

Vue源码学习(二)——生命周期的更多相关文章

  1. Vue源码学习二 ———— Vue原型对象包装

    Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...

  2. vue 源码学习二 实例初始化和挂载过程

    vue 入口 从vue的构建过程可以知道,web环境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compil ...

  3. Vue源码学习(二)$mount() 后的做的事(1)

    Vue实例初始化完成后,启动加载($mount)模块数据. (一)Vue$3.protype.$mount             标红的函数 compileToFunctions 过于复杂,主要是生 ...

  4. Vue源码学习三 ———— Vue构造函数包装

    Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...

  5. 手牵手,从零学习Vue源码 系列二(变化侦测篇)

    系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...

  6. Vue源码学习1——Vue构造函数

    Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...

  7. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  8. Dubbo源码学习(二)

    @Adaptive注解 在上一篇ExtensionLoader的博客中记录了,有两种扩展点,一种是普通的扩展实现,另一种就是自适应的扩展点,即@Adaptive注解的实现类. @Documented ...

  9. 最新 Vue 源码学习笔记

    最新 Vue 源码学习笔记 v2.x.x & v3.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 v2.x.x & v3.x.x ...

  10. 【Vue源码学习】依赖收集

    前面我们学习了vue的响应式原理,我们知道了vue2底层是通过Object.defineProperty来实现数据响应式的,但是单有这个还不够,我们在data中定义的数据可能没有用于模版渲染,修改这些 ...

随机推荐

  1. HDU 5858Hard problem

    Hard problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  2. 安卓BitmapFactory.decodeStream()返回null的问题解决方法

    问题描述: 从网络获取图片,数据为InputStream流对象,然后调用BitmapFactory的decodeStream()方法解码获取图片,返回null. 代码如下: private Bitma ...

  3. tab不显示为空格

  4. bzoj2125 最短路——仙人掌两点间距离

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 仙人掌!模仿 lyd 的代码写的,也算是努力理解了: 主要分成 lca 在环上和不在环 ...

  5. bzoj2744 [HEOI2012]朋友圈——二分图匹配

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744 首先,求一个图的最大团等价于求它的补图的最大独立集,而二分图的最大独立集 = 总点数 ...

  6. PCB MS SQL 标量函数(CLR) 实现DataTable转HTML的方法

    一.准备需转为HMLT字符串的DataTable数据 在数据库中执行一段SQL返回的数据 需转换后的HTML的文本 <html ><head></head>< ...

  7. 解决Sublime Text 3 的 Package Control 启动失败问题

    今天在使用Sublime Text的时候,需要了这样的情况         遇到这个问题的时候   我是这样解决的 一. 首先 找到 Package Control的下载地址1  下载地址2.将下载下 ...

  8. github fork项目更改后与原作者同步更新

    1.进入你的GitHub发起Pull request 2.选择compare across forks 3.反向操作.base fork改为自己的,head fork改为原作者的 4.点击 creat ...

  9. Comet OJ - Contest #3 题解

    传送门 太菜了连\(D\)都做不出来没有小裙子\(QAQ\) \(A\) 暴力把所有的数对都算出来,然后\(sort\)一下就行了 const int N=505; int a[N],st[N*N], ...

  10. Docker学习系列(一):windows下安装docker(转载)

    本文目录如下: windows按照docker的基本要求 具体安装步骤 开始使用 安装远程连接工具连接docker 安装中遇到的问题 Docker的更新 Docker中的jupyter windows ...