Vue的生命周期
一、Vue的生命周期
Vue的生命周期,生命周期其实就是一个vue组件从创建到销毁的过程。 主要经历了如下几个阶段,分别是 beforeCreate,created,beforeMount,mounted,beforeUpdate,update,beforeDestroy,destroy ,主要由这四对八个组成
主要分为四个流程,创建流程,挂载流程,更新流程和销毁流程
整个Vue的生命周期原理图如下:
1. 创建流程
创建流程分为beforeCreate和created两个阶段,注意此时创建的并不是vm,而是创建的数据监测和数据代理,创建流程如图所示:
1.1 beforeCreate阶段
创建完这个Vue实例之后,首先会进入一个初始化阶段,此阶段初始化生命周期和事件,在此阶段,数据代理还并没有开始。在初始化阶段之后,就会经历vue的 beforeCreate 阶段。
下面是我的Vue代码:
此时看浏览器的控制台并观察页面:
由于数据代理并未初始化,因此这个阶段是拿不到vm对象以及_data数据的,因此在第一个 beforeCreate 阶段中,无法通过这个vm对象访到data中的数据和methods中方法。并且是没有 _data 的,并且也没有data数据中的x 值,也没有add方法,前端页面的数据也不会进行编译解析
1.2 created阶段
在此阶段,还是处于一个初始化阶段,即init Injections & reactivity 阶段。该阶段就是初始化这个数据监测和数据代理的,这样就可以获取到代理对象并解析模板,对created进行debugger得到如下结果:
在初始化代理对象之后,就可以进入这个 created 阶段了。通过结果可以得知已经可以加载这个_data对象,由于初始化了这个数据监测,所以这个 get和set的两个方法也有了,由于初始化了这个数据代理,因此这个data中的x和method中的add都可以加载成功,注意此时是可以通过vm对象获取到 data 中的属性和method 中的方法的。
2. 挂载流程
创建流程之后,还会有一个阶段来解析这个Vue模版,即开始解析模板,生成虚拟DOM到内存中,此时页面还不能显示好解析的内容,即还没有转成真实DOM,然后进行beforeMount和mounted两个挂载流程阶段,挂载流程如图所示:
2.1 beforeMount阶段
执行到这这个 beforeMount 的时候,对应的页面是并没有进行解析的,可以确认beforeMount函数中的DOM元素是未经过Vue编译的,所有对Dom的操作最终都是不奏效的。其实这个DOM元素是Vue已经解析完成的真实DOM,但是此时的vue还没来的及将这些DOM向页面中存放,对beforeMount进行debugger,可以观察到:
可以发现页面上的值是原生的html,并不是经历过vue模板解析的值,因此可以得知上面还没有vue解析出来的DOM,同时也可以证明此时vue还没有来得及将编译的DOM存到页面中
2.2 mounted阶段
在 beforeMount 阶段之后,Vue会将el中的数据存放在 $el 上,类似于做一个副本,此时会将内存中的虚拟DOM转化为真实DOM存在页面中。在将真实的DOM插入页面之后,Vue就会开始调用这个 mounted 挂载函数。页面中已经呈现的是经过Vue编译的DOM,因此在这个函数中对DOM的操作均有效,在mounted函数中进行debugger可以观察到:
可以得知:在挂载阶段DOM元素已经是全部经过Vue解析的,因此展示在页面的值都是解析后的值,并且在这个阶段也可以有效的操作DOM元素。
在mounted函数中,一般会进行这些操作:开启定时器,发送网络请求,订阅消息,绑定自定义事件等操作
3. 更新流程
挂载流程结束之后,会进入更新流程,更新流程主要为 beforeUpdate 和 updated 两个阶段,更新流程如图所示:
3.1 beforeUpdate阶段
只要data中的数据发生改变,那么就会触发这个函数,但是在这个阶段中,页面上渲染的数据和被改变的数据没有保持同步,就是页面还没有来得及展示被修改的值,如图所示:
控制台打印结果如下:
通过以上结果可知,在这个阶段,vue实例中的数据和页面的数据是不一致的
3.2 updated阶段
beforeUpdate阶段结束之后,会经过一个 Virtual DOM re-render and patch 阶段,在这个阶段,就会生成新的虚拟DOM,随后通过diff算法,实现新旧的虚拟DOM的比较,最终完成页面的更新。
此时这个数据是新的,页面也是最新的,并且数据和页面是保持一致的,如图所示:
控制台打印结果:
通过以上结果可知,数据和页面是同步的
4. 销毁流程
最后一个流程,对于销毁流程,官网的解释是:清理它与其他实例的链接,解绑他的全部指令以及时间监听器。主要由beforeDestroy 和 destroyed两个部分组成。销毁流程如图所示:
4.1 beforeDestroy阶段
销毁需要调用这个 this.$destroy() 方法来实现,该阶段data,methods,指令等都处于可用状态,但是不能对实例中的具体的数据和方法进行一个操作。一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事件等。
首先我们先调用destroy(),如:设置一个按钮,给按钮绑定一个事件,这时只要点击按钮就会进入自动销毁流程,如图所示:
在点击销毁按钮之前,自增按钮还可以使用,当点击销毁按钮后,我们再点击自增按钮就没有用处了,进入销毁流程,如图所示:
控制台打印信息:
执行 beforeDestroy阶段时,在此阶段所有对数据的操作都不会生效,如图所示:
此时点击销毁按钮,进入beforeDestroy阶段后,会发现页面并没有执行x=100这一操作,页面中x的值没有发生改变,如图所示
4.2 destroyed阶段
此阶段是Vue生命周期的最后一个阶段,执行最终的销毁方法之后,vue实例算是彻底的被销毁了,但是页面上的数据是还在的,但是不能操作上面的数据,即清理它与其他实例的链接,解绑他的全部指令以及时间监听器
二、总结
常用的生命周期钩子:
1. mounted:发送ajax、启动定时器、绑定自定义事件、消息订阅等初始化操作
2. beforeDestroy:清除定时器、解绑自定义事件、取消消息订阅等
销毁vue实例之后
1. 借助vue开发者工具是看不到任何消息的
2. 销毁后自定义事件会失效,但是原生的DOM事件依然有效
3. 一般不要在beforeDestory中操作数据,因为该钩子并不会触发更新流程