【vue源码系列8】vue中的生命周期钩子是在哪执行的?

333 阅读3分钟

在前面介绍组件挂载的时候,介绍过mountComponent这个函数。

image.png

image.png

主要做三件事。(监听函数的主要逻辑在之前文章讲过一次,今天主要看第一步)

1.实例化组件,并处理数据

2.创建监听函数

3.挂载组件

今天来详细看看这个函数,在开始之前,不妨问问自己几个问题,看看能否回答上来。

1.同时在data和setup中,生命一个msg变量,哪个会生效呢?

2.nextTick是如何实现在dom更新之后触发的?

3.vue中的生命周期函数是如何触发的?


实例化

实例化比较简单,就是返回一个对象。(因为现在数据还没写进去) image.png

有个小知识点。

appContext取的是父级的appContext。

在vue2,如果全局绑定了属性,一般是通过this.$message这种形式来访问。但是在vue3中,没有了this,又想使用全局属性怎么办呢?

就可以使用getCurrentInstace获取组件实例,然后在appContext中获取。

在实例完之后,代码继续往下执行,在中间有一行不太起眼的代码,vue的数据就是在这里处理的。

image.png

我们进入这个函数,有几个需要注意的地方。

image.png

从名字也能看出来,initProps,initSlots是初始化属性跟插槽的。

那markRaw这一行是干啥的呢?直接进PublicInstanceProxyHandlers代理方法。

image.png

从这其实能看出来,组件取值会先从setup中找,其次是data。

setup处理

继续往下看,处理setup,并把setup返回值传入handleSetupResult。

image.png

image.png

判断setup结果类型,从这里可以看出来setup除了对象,是可以返回函数的,如果返回函数,则会作为渲染函数。

举个例子,在element-plus中,定义loading组件,就是通过setup返回函数来实现的。

image.png

finishComponentSetup

最后setup处理完之后,会finishComponentSetup函数。

在会finishComponentSetup函数中,还有一个重要的过程,就是制定render函数。如果没有则使用compile编译器来进行处理。

image.png

在这个函数中,主要看applyOptions(instance)函数。

image.png

生命周期来了,在这里,如果有beforeCreate,则执行钩子。 image.png

继续往后看,dataOptions就是data,如果设置了data,则通过call来改变上下文。(这就是为什么,this可以访问到数据)

image.png

数据处理好之后,就开始执行created钩子,然后注册其他生命周期。(因为其他生命周期不在这里出发,所以只是注册)

image.png

那这些函数在哪执行呢?。

在更新组件函数中,在执行组件更新之前。

image.png

nextTick

最后再来说说nextTick钩子函数。

实现非常简单。

在之前组件更新中,有一个核心的知识点是:vue在数据变化时,会触发组件更新,为了避免重复执行更新函数,使用了微任务队列,等数据都更新完了之后,再统一执行组件更新函数。

nextTick的实现就是把钩子放到微任务队列中,等组件更新函数执行完之后,再执行。

export function nextTick<T = void>(
  this: T,
  fn?: (this: T) => void
): Promise<void> {
  const p = currentFlushPromise || resolvedPromise
  return fn ? p.then(this ? fn.bind(this) : fn) : p
}

总结

总结一下今天的知识点。

1.appContext在上下文的时候,指定为父级appContext。(也就是全局上下文)

2.vue的变量访问顺序,做了统一的代理,先setup,其次是data。

3.setup可以返回函数作为渲染函数。

4.组件实例如果没有render函数,会使用compile编译

5.vue2写法,this之所以能访问到,是因为做了this重定向

6.生命周期在处理组件数据的各个阶段调用

7.nextTick之所以能在组件更新执行完成之后执行,是因为用了微任务。


如果看完有收获,欢迎点赞、评论、分享支持。你的支持和肯定,是我写作的动力