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

从图中我们可以看到我们的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

最新文章

  1. android3D动画,绕y轴旋转
  2. dojo Provider(script、xhr、iframe)源码解析
  3. 7.django之自定义分页记录
  4. 常用的Expression调用形式
  5. Linux常用命令_(进程管理)
  6. php + mysql + sphinx 的全文检索(2)
  7. no-cache、max-age=0、must-revalidate区别
  8. mysql中取系统当前时间
  9. JQuery 的基本命令
  10. 未能加载文件或程序集“xxxx”或它的某一个依赖项
  11. jstree 学习
  12. 如何扩展VS2017未安装的功能
  13. Python中xlutils解析
  14. LeetCode(77):组合
  15. Educational Codeforces Round 60 C 思维 + 二分
  16. Chapter 2 Open Book——26
  17. install ubuntu on Android mobile phone
  18. node.js 连接 sql server 包括低版本的sqlserver 2000
  19. 〖Windows〗zigbee实验之cygwin编译TestSimpleMac出错的解决方法
  20. 用C/C++开发android应用

热门文章

  1. eclipse 自己主动为getter和setter加入中文凝视
  2. oc72--NSArray排序
  3. Linux 数据分析常用 shell命令
  4. luogu 3690 【模板】 Link Cut Tree (动态树)
  5. 在Struts2中ognl.MethodFailedExceptiond异常的解决办法
  6. E20170807-mk
  7. HttpPostedFileBase 基类
  8. ansible剧本
  9. MySQL简明教程---级联约束
  10. Android从Camera中获取图片的两种方法