Fram/Lib

VUE生命周期

字数:3709    阅读时间:19min
阅读量:18286

什么是vue的生命周期:在我们创建一个vue实例的时候vue内部是会做很多事情的,这个实例从创建到运行再到销毁,会触发vue里的一系列事件,这些事件就是vue的生命周期;vue的生命周期大致分为四个阶段:创建阶段,挂载阶段,运行阶段,销毁阶段;以下是生命周期示意图可供参考:

vue生命周期

一、实例创建阶段

实例创建阶段示意图

beforeCreate:实例被创建之前;在我们创建一个vue实例的时候,vue内部首先初始化实例的所有默认事件和生命周期函数,之后就有了第一个生命周期函数beforeCreate;在这个阶段的函数拿不到实例的任何数据;

created:实例被创建之后;实例在经历完beforeCreate之后,会继续初始化实例里的data数据和methods里的方法,并将data里的每一个属性都添加上getter和setter便于后期观测做到数据响应式(数据观测);这个阶段可以访问到vue里的一些数据,可以发送异步请求(但是注意这里边异步请求时间长了容易造成白屏现象),但是挂载阶段还没开始,$el属性是不可访问的

二、实例挂载阶段

在实例挂载之前还有一个模板编译阶段,1、在这个阶段vue会判断当前实例是否有el选项,如果有则继续判断是否有template属性;如果没有el选项,那么vue的生命周期到就会停止,只有当手动调用vm.$mount(el)时生命周期才继续运行;2、然后再判断当前实例是否有template选项,如果有就将template作为模板编译成渲染函数,如果没有template就将el的外部HTML作为template进行编译。当同时存在template和el时,当然是将template作为模板进行编译;vue其实还有render选项,当render选项存在时他们的优先级是:render > template > el外部HTML

模板编译阶段示意图

模板编译结束之后就来到了实例挂载的阶段

实例挂载阶段示意图

beforeMount:实例挂载之前;在完成模板编译之后就会触发beforeMount生命周期函数,在这个阶段虚拟DOM已经被渲染可以访问到$el,但是还没有挂载到对应的真实DOM上所以还访问不到$refs,真是DOM上的{{}}数据也是没有的

mounted:实例挂载之后;在beforeMounted之后,vue用渲染好的vm.$el替换原先的el,这个时候实例已经挂载在DOM上了(此时的DOM是vue渲染的DOM),可以通过$refs正常访问这个DOM,这个DOM里的{{}}数据也被替换

带有子组件的实例的生命周期:(父)beforeCreate---(父)created---(父)beforeMount---(子)beforeCreate---(子)created---(子)beforeMount---(子)mounted---(父)mounted---(父)beforeUpdate--(子)beforeUpdate---(子)updated---(父)updated---(父)beforeDestory---(子)beforeDestory---(子)destoryed---(父)destoryed ;当有混入组件mixin的时候mixin组件的所有周期函数要优先执行;注意mounted不承诺所有组件全都挂载完成,如果想要确保整个视图渲染完毕需要使用vm.nextTick

三、实例运行阶段

实例运行阶段示意图

在完成挂载之后就进行到了运行阶段,在有数据发生该变的时候,就会触发update阶段将虚拟DOM重新渲染并更新到页面DOM;注意这里只有改变写在模板里的数据才会触发这个阶段 ,改变没有写在模板里的数据是不会触发数据更新阶段的

beforeUpdate:数据更新前,更准确的说是DOM更新前;;在重新渲染虚拟DOM之前,vue给出一个beforeUpdate钩子函数。可以用来操作更新前的DOM;注意:在beforeUpadte中打印没有改变的原DOM,因为不管是$el还是$refs都是对象,在控制台打印的时候updated已经触发了,这个时候打印的$el和$refs都是updated改变后的对象了(其实beforeUpdate中访问的$el就是原来的那个DOM),我们可以在打印的时候加上innerHTML或者outerHTML就可以看到打印之前的DOM了;

updated:DOM更新完之后;在经历了重新渲染虚拟DOM并更新应用到页面之后就来到了vue的updated阶段,这个阶段的DOM就是已经更新过的DOM;注意:updated也不保证所有的子组件都已经重绘,如果需要等到整个视图更新完毕再做操作可以使用vm.nextTick(function(){})

在有keep-alive导航守卫的时候组件还会额外触发以下生命周期函数

activetad:keep-alive组件激活的时候触发该函数

deactivated:keep-alive组件销毁的时候触发该函数

有路由守卫的生命周期和路由守卫的触发顺序:

  1. 全局前置守卫 beforeEach
  2. 在导航被确认之前触发 beforeResolve
  3. 在路由确认前调用 beforeRouteEnter,在生命周期钩子之前
  4. 组件生命周期钩子函数 beforeCreate,组件实例刚被创建,属性生效之前
  5. 组件生命周期钩子函数 created,实例已经创建完成,属性已绑定,但是DOM还未生成,适合初次获取数据
  6. 组件生命周期钩子函数 beforeRouteLeave,导航离开当前路由前触发
  7. 组件生命周期钩子函数 beforeMount,挂载之前,render函数或template编译成虚拟DOM之后
  8. 组件生命周期钩子函数 mounted,挂载完成,真实DOM挂载在页面后调用,适合初始化数据
  9. 路由独享守卫 beforeRouteUpdate,当前路由更新时调用
  10. 组件生命周期钩子函数 activated,keep-alive组件激活时调用
  11. 组件生命周期钩子函数 beforeUpdate,数据更新时调用,发生在虚拟DOM重新渲染之前
  12. 组件生命周期钩子函数 updated,数据更新后调用
  13. 组件生命周期钩子函数 deactivated,keep-alive组件停用时调用
  14. 全局前置守卫 afterEach
  15. 组件生命周期钩子函数 beforeDestroy,实例销毁前调用,适合移除事件监听、定时器等
  16. 组件生命周期钩子函数 destroyed,实例销毁后调用

四、实例销毁阶段

实例销毁阶段示意图

beforeDestor:实例销毁之前调用;在我们销毁当前实例之前所作的事情可以写在这里,这个时候实例还在this还可以访问,一般会在这个阶段销毁定时器、解绑全局事件、销毁插件对象等的善后操作

destroyed:实例销毁之后调用;这个时候实例已经被销毁,所有的东西都会解绑this无法访问,所有子实例也都被销毁; 它只是完全销毁一个vue实例,清理它与其他实例的链接,解绑它所有的指令和事件监听器,并不会清除页面上的DOM

errorCaptured :当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误的对象、发生错误的组件实例、错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

你可以在此钩子中修改组件的状态。因此在捕获错误时,在模板或渲染函数中有一个条件判断来绕过其它内容就很重要;不然该组件可能会进入一个无限的渲染循环。

错误传播规则

  • 默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。
  • 如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
  • 如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler
  • 一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler

野生小园猿
励志做一只遨游在知识海洋里的小白鲨
查看“野生小园猿”的所有文章 →

相关推荐