vue生命周期详解简书,简述vue生命周期的含义

  vue生命周期详解简书,简述vue生命周期的含义

  在实际的项目开发过程中,我们会非常频繁地处理Vue组件的生命周期。接下来,我们将从源代码的角度来看这些生命周期的钩子函数是如何执行的。有需要的可以参考下面这篇文章。

  

目录

   1、创建前创建2、挂载前挂载3、更新前更新4、销毁前销毁5、激活停用前言:

  每个Vue实例在创建之前都要经历一系列初始化过程。例如,您需要设置数据监控、编译模板、将实例挂载到DOM,以及在数据发生变化时更新DOM。同时,在这个过程中还会运行一些被称为生命周期钩子的函数,让用户有机会在一些特定的场景下添加自己的代码。

  源代码中最终执行生命周期的函数都调用callHook方法,它的定义在 src/core/instance/lifecycle 中:

  导出函数callHook (vm: Component,hook: string) {

  //#7573调用生命周期挂钩时禁用dep收集

  pushTarget()

  常量处理程序=虚拟机。$ options[挂钩]

  if(处理程序){

  for(设i=0,j=handlers.lengthI j;i ) {

  尝试{

  经手人[我]。呼叫(虚拟机)

  } catch (e) {

  handleError(e,vm,` ${hook} hook `)

  }

  }

  }

  如果(vm。_hasHookEvent) {

  vm。$emit(hook: hook )

  }

  popTarget()

  }

  callHook函数的逻辑非常简单。根据传入的字符串钩子,获取vm对应的回调函数数组。$options[hook],然后遍历执行。执行时,以vm为函数执行的上下文。

  

1、beforeCreate created

  在Vue的实例化过程中,create和created函数都在_init方法中执行,其定义在src/core/instance/init.js中:

  Vue.prototype._init=function(选项?对象){

  //.

  初始生命周期(虚拟机)

  初始化事件(虚拟机)

  初始化渲染(虚拟机)

  callHook(虚拟机,“创建前”)

  initInjections(vm) //在数据/属性之前解析注入

  初始化状态(虚拟机)

  initProvide(vm) //在数据/属性之后解析提供

  callHook(虚拟机,“已创建”)

  //.

  }

  可以看到beforeCreate和created的钩子调用在initState之前和之后。initState的功能是初始化属性,如props、data、methods、watch、computed等。之后我们再详细分析。显然,beforeCreate的hook函数无法获取props和data中定义的值,也无法调用方法中定义的函数。

  当这两个钩子函数被执行时,DOM没有被渲染,所以我们也不能访问DOM。一般来说,如果一个组件在加载时需要和后端交互,可以在这两个钩子函数中执行。如果需要访问道具、数据等数据,需要使用创建的hook函数。后面介绍vue-router和vuex的时候会发现,两者都是混合了beforeCreatd hook函数的。

  

2、beforeMount mounted

  顾名思义,beforeMount钩子函数发生在Mount中,也就是DOM挂载之前,它的调用时间在mountComponent函数中,这个函数是在src/core/instance/lifecycle.js中定义的:

  导出函数mountComponent(

  vm:组件,

  el:元素,

  补水?布尔型

  ):组件{

  vm。$el=el

  //.

  callHook(虚拟机,“装载前”)

  让更新组件

  /*伊斯坦布尔忽略if */

  if (process.env.NODE_ENV!==生产配置.性能标志){

  updateComponent=()={

  const name=vm。_name

  const id=vm。_uid

  const start tag=` vue-perf-start:$ { id } `

  const end tag=` vue-perf-end:$ { id } `

  标记(开始标记)

  const vnode=vm。_render()

  标记(结束标记)

  measure(`vue ${name} render `,startTag,endTag)

  标记(开始标记)

  vm。_更新(虚拟节点,补水)

  标记(结束标记)

  测量(` vue ${name} patch `,startTag,endTag)

  }

  }否则{

  updateComponent=()={

  vm。_更新(虚拟机。_render(),补水)

  }

  }

  //我们把这个设置为vm。观察器构造函数中的观察器(_ w)

  //由于观察器的初始补丁可能调用$forceUpdate(例如在儿童内部

  //组件的挂载钩子),它依赖于虚拟机.已经定义了_观察者

  新观察器(虚拟机、更新组件、noop 、{

  之前(){

  如果(虚拟机._isMounted) {

  呼叫挂钩(虚拟机,"更新前")

  }

  }

  },true /* isRenderWatcher */)

  补水=假

  //手动装入实例,调用装入自身

  //在其插入的挂钩中为呈现创建的子组件调用安装好的

  如果(虚拟机.$vnode==null) {

  虚拟机._isMounted=true

  调用挂钩(虚拟机,"已安装")

  }

  返回虚拟机

  }

  在执行虚拟机.渲染()函数渲染虚拟节点之前,执行了即将挂载钩子函数,在执行完虚拟机.更新()把虚拟节点补丁到真实数字正射影像图后,执行mouted钩子。注意,这里对mouted钩子函数执行有一个判断逻辑,虚拟机.$vnode如果为空,则表明这不是一次组件的初始化过程,而是我们通过外部新某视频剪辑软件初始化过程。那么对于组件,它的安装好的时机在哪儿呢?

  组件的虚拟节点补丁到数字正射影像图后,会执行invokeInsertHook函数,把insertedVnodeQueue里保存的钩子函数依次执行一遍,它的定义在src/core/vdom/patch.js中:

  函数invokeInsertHook (vnode,queue,initial) {

  //延迟组件根节点的插入挂钩,在

  //元素确实被插入

  if(为真(初始)isDef(vnode。父级)){

  vnode。父母。数据。挂起插入=队列

  }否则{

  对于(设I=0;我队列长度;i) {

  队列[I]。数据。钩子。插入(队列[I])

  }

  }

  }

  该函数会执行插入这个钩子函数,对于组件而言,插入钩子函数的定义在src/core/vdom/create-component射流研究…中的componentVNodeHooks中:

  const componentVNodeHooks={

  //.

  insert(vnode:MountedComponentVNode){

  const { context,componentInstance }=vnode

  如果(!组件实例. isMounted) {

  组件实例. isMounted=true

  callHook(组件实例,"已安装")

  }

  //.

  },

  }

  我们可以看到,每个子组件都是在这个钩子函数中执行mouted钩子函数,并且我们之前分析过,插入的VnodeQueue的添加顺序是先子后父,所以对于同步渲染的子组件而言,已安装钩子函数的执行顺序也是先子后父。

  

3、beforeUpdate updated

  顾名思义,更新前和更新的钩子函数执行时机都应该是在数据更新的时候,到目前为止,我们还没有分析某视频剪辑软件的数据双向绑定、更新相关,下一章我会详细介绍这个过程。

  更新前的执行时机是在渲染看守人的以前函数中

  导出函数安装组件(

  虚拟机:组件,

  el:元素,

  补水?布尔型

  ):组件{

  //.

  //我们把这个设置为虚拟机.观察器构造函数中的观察器(_ w)

  //由于观察器的初始补丁可能调用$forceUpdate(例如在儿童内部

  //组件的挂载钩子),它依赖于虚拟机.已经定义了_观察者

  新观察器(虚拟机、更新组件、noop 、{

  之前(){

  如果(虚拟机._isMounted) {

  呼叫挂钩(虚拟机,"更新前")

  }

  }

  },true /* isRenderWatcher */)

  //.

  }

  注意这里有个判断,也就是在组件已经安装好的之后,才会去调用这个钩子函数。

  更新的执行时机是在flushSchedulerQueue函数调用的时候,它的定义在src/core/observer/scheduler.js中:

  函数flushSchedulerQueue () {

  //.

  //获取到更新队列

  callUpdatedHooks(updatedQueue)

  }

  函数callUpdatedHooks(队列){

  设i=队列长度

  while (i - ) {

  常量观察器=队列[i]

  const vm=watcher.vm

  如果(虚拟机._watcher===观察程序虚拟机._isMounted) {

  呼叫挂钩(虚拟机,"已更新")

  }

  }

  }

  flushSchedulerQueue函数我们之后会详细介绍,可以先大概了解一下,更新队列是更新了的沃特斯彻数组,那么在callUpdatedHooks函数中,它对这些数组做遍历,只有满足当前看守人为虚拟机._观察者以及组件已经安装好的这两个条件,才会执行更新钩子函数。

  我们之前提过,在组件增加的过程中,会实例化一个渲染的看守人去监听伏特计上的数据变化重新渲染,这断逻辑发生在安装组件函数执行的时候:

  导出函数安装组件(

  虚拟机:组件,

  el:元素,

  补水?布尔型

  ):组件{

  //.

  //这里是简写

  让updateComponent=()={

  虚拟机._更新(虚拟机. render(),补水)

  }

  新观察器(虚拟机、更新组件、noop 、{

  之前(){

  如果(虚拟机._isMounted) {

  呼叫挂钩(虚拟机,"更新前")

  }

  }

  },true /* isRenderWatcher */)

  //.

  }

  那么在实例化看守人的过程中,在它的构造函数里会判断isRenderWatcher,接着把当前看守人的实例赋值给虚拟机._watcher,定义在src/core/observer/watcher.js中:

  导出默认类观察器{

  //.

  构造器(

  虚拟机:组件,

  expOrFn: string Function,

  cb:功能,

  选项?对象,

  isRenderWatcher?布尔型

  ) {

  this.vm=vm

  if (isRenderWatcher) {

  虚拟机._watcher=这

  }

  虚拟机._watchers.push(本)

  //.

  }

  }

  同时,还把当前沃特斯彻实例推到虚拟机.观察者中,虚拟机.看守人是专门用来监听伏特计上数据变化然后重新渲染的,所以它是一个渲染相关的观察者,因此在callUpdatedHooks函数中,只有虚拟机._观察者的回调执行完毕后,才会执行更新钩子函数。

  

4、beforeDestroy destroyed

  顾名思义,销毁前和破坏钩子函数的执行时机在组件销毁的阶段,组件的销毁过程之后会详细介绍,最终会调用$销毁方法,它的定义在src/核心/实例/生命周期。射流研究…中:

  vue。原型。$ destroy=function(){

  常量vm:组件=这个

  如果(虚拟机._ isbeingdestored){

  返回

  }

  呼叫挂钩(虚拟机,"销毁前")

  虚拟机._ isBeingDestroyed=true

  //从父代中移除自身

  const parent=vm .$parent

  如果(家长!父母. isBeingDestroyed!虚拟机.$options.abstract) {

  移除(父$儿童,vm)

  }

  //拆卸观察器

  如果(虚拟机._watcher) {

  虚拟机._watcher.teardown()

  }

  设i=vm ._观察者。长度

  while (i - ) {

  虚拟机._watchers[i].拆卸()

  }

  //从数据鄂毕河(Ob)中删除引用

  //冻结的对象可能没有观察者。

  如果(虚拟机._data .__ob__) {

  虚拟机._data .__ob__ .虚拟机计数-

  }

  //调用最后一个钩子.

  虚拟机._isDestroyed=true

  //调用当前呈现树上的销毁挂钩

  虚拟机.__补丁_ _(虚拟机. vnode,null)

  //火毁钩

  呼叫挂钩(虚拟机,"已销毁")

  //关闭所有实例侦听器。

  虚拟机.$off()

  //删除__vue__引用

  如果(虚拟机.$el) {

  虚拟机.亿美元.__vue__=null

  }

  //释放循环引用(#6759)

  如果(虚拟机.$vnode) {

  虚拟机.$vnode.parent=null

  }

  }

  销毁前钩子函数的执行时机是在破坏函数执行最开始的地方,接着执行了一系列的销毁动作,包括从父母的孩子们中删掉自身,删除观察者,当前渲染的虚拟节点执行销毁钩子函数等,执行完毕后再调用破坏钩子函数。

  在$销毁的执行过程中,它又会执行虚拟机.补丁(虚拟机._vnode,null)触发它子组件的销毁钩子函数,这样一层层的递归调用,所以破坏钩子函数执行顺序是先子后父,和安装好的过程一样。

  

5、activated deactivated

  激活的和无效的钩子函数是专门为点火电极组件定制的钩子,我们会在介绍点火电极组件的时候详细介绍,这里先留个悬念。

  总结:

  本节主要介绍Vue生命周期中各个钩子函数的执行时序和顺序。通过分析我们知道,在创建的钩子函数中可以访问数据,在挂载的钩子函数中可以访问DOM,在销毁钩子函数中可以进行定时器销毁。了解它们有助于我们在适当的生命周期做不同的事情。

  这篇带你了解Vue生命周期的文章到此结束。有关Vue生命周期的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: