Vue框架已日臻成熟,生命周期也算是老生常谈了。网路上也有很多对Vue生命周期的讲解。

此处是补充上自己的理解,再次总结一下。

一、什么是生命周期(LifeCycle)?

生命周期在计算机语言里,生命周期一般是指一个对象的创建(生)到销毁(死)的阶段。

二、Vue的生命周期

2.1 生命周期图解

对于Vue的生命周期,就是其组件的生命周期。具体可以看下图(相对官方文档的图,已补充翻译):

vue-lifecycle(该翻译图忘记来源,有知道绘制作者提供下).png

从图中可以直观注意到,Vue的生命周期可以划分为四个阶段:

create 阶段: vue实例被创建;

mount 阶段: vue实例被挂载到真是的DOM节点;

update 阶段:当vue实例里面的data数据变化时,触发组件的重新渲染;

destroy 阶段:vue实例被销毁。

2.2 阶段分解

上面的四个阶段,每个阶段分为开始前和开始后,这样就衍生出了9个方法:

beforeCreate

created

beforeMount

mounted

beforeUpdate

updated

beforeDestroy

destroyed

——也就是所谓的钩子函数。

接下来我们一个阶段一个阶段来分析它们的触发条件及表征。

2.2.0 实验代码准备

(1)一个最简单的Vue实例化代码如下:

{{ message }}

var vm = new Vue({

el: '#app',

data: {message: 'Hello Vue~'},

});

我们主要关心着这个实例化里的属性:元素el什么时候有值(挂载上了?)、data什么时候有数据?、message又是什么时候有数据呢?

于是,我们在每个回调里面去打印下这三个值看看。

(2)为了更直观去理解Vue实例的变化,我们引用了一段实验代码(该源码来源于参考文章1):

{{ message }}

var vm = new Vue({

el: '#app',

data: {message: 'Hello Vue~'},

beforeCreate: function(){

console.group('beforeCreate 创建前 =========')

console.log('%c%s','color:red','el :',this.$el) // 1 => undefined

console.log('%c%s','color:red','data :',this.$data) // 1 => undefined

console.log('%c%s','color:red','message :',this.message) // 1 => undefined

},

created: function(){

console.group('created 创建完毕 =========')

console.log('%c%s','color:red','el :',this.$el) // 1 => undefined

console.log('%c%s','color:red','data :',this.$data) // 1 => {message: 'Hello Vue~'}

console.log('%c%s','color:red','message :',this.message) // 1 => 'Hello Vue~'

},

beforeMount: function(){

console.group('beforeMount 挂载前 =========')

console.log('%c%s','color:red','el :',this.$el) // 1 =>

{{ message }}

console.log('%c%s','color:red','data :',this.$data) // 1 => {message: 'Hello Vue~'}

console.log('%c%s','color:red','message :',this.message) // 1 => 'Hello Vue~'

},

mounted: function(){

console.group('mounted 挂载结束 =========')

console.log('%c%s','color:red','el :',this.$el) // 1 =>

'Hello Vue~'

console.log('%c%s','color:red','data :',this.$data) // 1 => {message: 'Hello Vue~'}

console.log('%c%s','color:red','message :',this.message) // 1 => 'Hello Vue~'

},

beforeUpdate: function(){

console.group('beforeUpdate 更新前 =========')

console.log('%c%s','color:red','el :',this.$el) // 2 =>

'Celine~'

console.log('%c%s','color:red','data :',this.$data) // 2 => {message: 'Celine~'}

console.log('%c%s','color:red','message :',this.message) // 2 => 'Celine~'

},

updated: function() {

console.group('updated 更新完成 =========')

console.log('%c%s','color:red','el :',this.$el) // 2 =>

'Celine~'

console.log('%c%s','color:red','data :',this.$data) // 2 => {message: 'Celine~'}

console.log('%c%s','color:red','message :',this.message) // 2 => 'Celine~

},

beforeDestroy: function(){

console.group('beforeDestroy 销毁前 =========')

console.log('%c%s','color:red','el :',this.$el) // 3 =>

'Celine~'

console.log('%c%s','color:red','data :',this.$data) // 3 => {message: 'Celine~'}

console.log('%c%s','color:red','message :',this.message) // 3 => 'Celine~

},

destroyed: function(){

console.group('destroyed 销毁完成 =========')

console.log('%c%s','color:red','el :',this.$el) // 3 =>

'Celine~'

console.log('%c%s','color:red','data :',this.$data) // 3 => {message: 'Celine~'}

console.log('%c%s','color:red','message :',this.message) // 3 => 'Celine~

}

})

// 1 页面直接刷新进来,执行的钩子有 beforeCreate / created / beforeMount / mounted 四个。

// 2 在控制台执行 vm.message = "Celine~" 后,执行的钩子有 beforeUpdate / updated 两个。

// 更新前和更新后的,打印数据均是新数据 ?? 这点和想象的不太一致。

// 3 在控制台执行 vm.$destroy() 后,执行的钩子有 beforeDestroy / destroyed 两个。

// 销毁前和销毁后,数据依旧存在?? 这点也和想象的不太一致。不过这个时候再去改变message值,vue不会再响应(也不会去执行beforeUpdate / updated 钩子)

// 4 在控制台执行 vm.message = "Bye~" ,没有任何钩子有响应。

返回结果:

由此可见,当代码运行时,会一次调用Vue 的 beforeCreate、created、beforeMount、mounted 四个方法,直至完成组件的挂载。

而update阶段,要在数据发生改变时(比如更新message字段 vm.message = 'Hahahaha~')才出发;destroy阶段,要在调用vm.$destroy()后才触发。

下面我们来分别分析每个阶段:

2.2.1 create阶段

从生命周期图可以看出,在这个阶段主要做两件事:

监控Data数据

初始化内部事件

从控制台打印数据,可以看出:在beforeCreate时,因为啥动作都还没有开始,所以vm.$el,vm.$data,vm.message都是undefined。

而在created时,因为已开始监控Data数据,所以data,message都有值。至于初始化内部事件是什么,我们此处暂不表,后续补充。

2.2.2 mount阶段

在这个阶段,做的事情就比较多了。

挂载前:

先判断是否有el选项(我们的上方示例代码中有该选项,即el: '#app',);

如果有el选项,接着判断是否有template选项(此处我们的示例代码中并没有该选项);

如果有template选项,编译该模板并导入到渲染函数;如果没有template选项,就把实例模板el指向的DOM的outerHTML(上方示例代码即为

{{ message }}

)作为模板.

挂载后:

创建vm.$el,并用上面编译好的模板(html内容)替换el指向的DOM。

从控制台打印数据就可以看出:

挂载前,vm.$el为

{{ message }}

,看起来似乎有值了,但又不太对劲——因为message的值没有代入进入。其实此处有点像虚拟DOM的效果:也就是我的vm.$el虽然不是完整的,但也先准备着。(所以,在其他版本的浏览器中,此处也可能是打印出undefined。)

挂载结束就不一样了,三个数据项都就绪了。vm.$el也成为了完美的

Hello Vue~

以上的结果是按照有el选项,没有template选项的情况执行的。接下来我们看看其他种情况下,会发生点什么?

(1)没有el选项

操作:注释掉 el: "#app"

结果:只进行了create阶段,没有进行mount阶段。

原因分析:这个好理解,因为没有了el选项,就无从挂载起了。生命周期也就结束了。

如果此时想进行挂载,可以手动去调用vm.$mount(el)。

(2)手动挂载

操作:在new Vue({...})后面执行 vm.$mount('#app')

结果:进行了create阶段后,也进行了mount阶段。

(3)有template选项时

之前的实例代码是没有template选项的情况表现,此处我们看下若有template选项,会发生点什么呢?

var vm = new Vue({

el: '#app',

data: {message: 'Hello Vue~'},

template: "

我是模板标题1

",

}

操作: 在new Vue({...})里新增 template选项,如上。

结果: vm.$el变成了template选项的内容;DOM节点#app也替换成template选项的内容了。其实挂载后,vm.$el是什么,DOM节点#app也对应是什么,它们是等价的。

分析: 此处验证了前面生命周期图:若有template选项,就编译它并导入到渲染函数;若没有template选项,就取#app的outerHTML作为模板。

(4)render()方法

Vue实例里还有render()方法可以提供模板,我们看下如果存在render()方法,会发生什么?

var vm = new Vue({

el: '#app',

data: {message: 'Hello Vue~'},

template: "

我是模板标题1

",

render(h){

return h('h2','这是render出来的标题2');

},

}

操作: 在new Vue({...})里新增 render(h)方法,如上。

结果: vm.$el变成了render返回的模板内容。

分析: 也就是说,渲染模板的优先级可以小结为:render()方法 > template选项 > el属性的outerHTML。

以上就是挂载阶段的一序列可能性变化。接下来我们看下更新阶段。

2.2.3 update阶段

更新阶段的前提是:“when data changes”也就是说当data选项里的数据有变化时触发。

让数据改变有很多操作方式,此处我们简单的在控制台对message字段进行改写。

// 在控制台输入:

vm.message = "Now update!!" //直接回车

当进行了数据更新,就会触发beforeUpdate方法和 updated方法。

此处在控制台打印出来的数据和预想的有出入:beforeUpdate本应该输出的旧数据(message: Hello Vue~),但此处更新前后的数据却显示一样。

在参考文章2里面,说这是打印出来的是虚拟DOM,都已更新,但真实DOM还没有改变。但我个人觉得不一定是这样。我尝试过在各个钩子函数补充打印出DOM元素(如下代码),但结果更新前后也都是更新后的数据。

console.log('%c%s','color:red','#app DOM :',document.getElementById("app"))

我个人更倾向于是因为控制台本身原因。在beforeUpdate时可能确实是旧数据,只不过往下执行updated时候,更新新数据时,也改写了beforeUpdate部分的数据。(待进一步探讨研究补充。)

2.2.4 destroy阶段

image.png

销毁阶段,需要执行vm.$destroy()才会进入。

同样的,我们在控制台执行销毁方法,得到如下结果:

可以看出,销毁前后的数据是一样的,但实际上,销毁后Vue实例会接触所有绑定,所有事件被移除,子组件被销毁。比如我们此处更新 data 数据项 vm.message,可以发现,不会在触发update阶段了。

2.3 生命周期小结

我们对上面的分析结果做个小结,此处的表格会多考虑两个方法(当有组件时,生命周期会多出现一个activate阶段)。

方法名

特征

属性变化

beforeCreate

组件实例创建前(或者说刚被创建),啥也没有。

$el、data 的值都为undefined。

created

组件实例创建完成。属性已绑定,但DOM还未产生。

data有值了,$el属性还是undefined。

beforeMount

模板编译/挂载前。

$el是虚拟DOM。

mounted

模板编译/挂载后。

“虚拟”的dom节点被真实的dom节点替换,并将其插入到dom树中。此时可以获取到$el为真实的dom元素。

beforeUpdate

组件更新之前。

$el、data 的值都为新数据。

updated

组件更新之后。

$el、data 的值都为新数据。

activated

for kepp-alive,组件被激活时调用。

(待补充)

deactivated

for kepp-alive,组件被移除时调用。

(待补充)

beforeDestroy

组件销毁前嗲用。此时实例仍可用。

$el、data 都有值。实例绑定的事件还存在。

destroyed

组件销毁后调用。

$el、data 虽然都有值。但实例绑定的事件和子组件都没有了。

3 了解生命周期的作用

我们去关注声明周期,是为了能更好的判断在不同的生命周期钩子函数里面做些什么操作和处理。比如:

beforeCreate - 加入loading事件

created - 结束loading

beforemount - 发起服务端请求,取数据

mounted - 根据请求数据,对页面DOM做些什么操作

……

具体每个阶段的做些什么,还是要根据实际场景来设定咯~

-----------------------HAPPY END--------------------------------

参考文献:

vue 生命周期 返回不触发_Vue生命周期小结相关推荐

  1. vue 生命周期 返回不触发_Vue生命周期activated之返回上一页不重新请求数据操作...

    activated: 英文原意:使活动.触发 在Vue的生命周期函数中,这个好像用的不是特别多?(也许只是在我的工作中这个用的不多,或者说叫几乎不用这个) 一.需求 前不久在项目中有这样一个需求: 在 ...

  2. vue声明周期_Vue生命周期的理解

    当面试官问:"谈谈你对vue的生命周期的理解",听到这句话你是不是心里暗自窃喜:这也太容易了吧,不就是beforeCreate.created.beforeMount.mounte ...

  3. vue openlayer单击地图事件循环多次执行_VUE生命周期函数面试题

    什么是 vue 生命周期 vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数实现组件数据管理和DOM渲染两大重 ...

  4. Vue学习(watch、computed、生命周期、filter)- 学习笔记

    文章目录 Vue学习(watch.computed.生命周期)- 学习笔记 watch 监听 computed 计算属性 set---动态添加属性 delete---删除 生命周期 filter 过滤 ...

  5. mounted钩子函数_vue生命周期钩子函数的正确使用方式

    先上图 vue的生命周期 遇到的一个问题 在我的项目中,常用的生命周期钩子函数一直都是mounted,对于大部分情况,都是屡试不爽.捷报频传~ 但是在前几天却遭遇了一个意外,我在mounted中获取后 ...

  6. 页面生命周期onShow没有触发

    现象描述: 通过router.push接口跳转到快应用的B页面,当B页面只是引用一个自定义组件XX的时候,B页面的onShow生命周期无法触发.如下图所示: 代码如下:       B页面代码: 1 ...

  7. vue生命周期函数、react生命周期函数、微信小程序生命周期函数、uni-app生命周期函数,简介及图示

    vue生命周期函数 beforeCreate (创建前) created (创建后) beforeMount (挂载前) mounted (挂载后) beforeUpdate (数据更新前) upda ...

  8. android应用程序的生命周期,Android应用程序的生命周期.doc

    Android应用程序的生命周期.doc Android应用程序的生命周期 描述:程序的生命周期是在Android系统中进程从启动到终止的所有阶段,也就是Android从启动到停止的全过程.==程序的 ...

  9. android viewpager fragment 生命周期,ViewPager中Fragment的生命周期

    网上有很多Fragment生命周期的帖子,但是看了一下,没有找到自己想了解的东西,于是决定自己动手体验一下这个生命周期.主要想了解以下几个问题: Activity中的Fragment的生命周期 Vie ...

最新文章

  1. PyTorch: 序列到序列模型(Seq2Seq)实现机器翻译实战
  2. 金蝶K/3 BOS产品培训教案
  3. 【转】并行计算、分布式计算、集群计算和云计算
  4. [caffe解读] caffe从数学公式到代码实现2-基础函数类
  5. centos6.5下如何把python2.6.6升级到2.7
  6. pytest测试实战pdf_Pytest+Allure美化测试报告
  7. Gson格式转换Integer变为Double类型问题解决
  8. error: ‘PRIO_PROCESS’ undeclared
  9. 特征选择算法-Relief
  10. JAVA复习 (期末重点考点总结)
  11. ppt流程图按步骤链接_【PPT教程】在PowerPoint中5分钟制作一个流程图
  12. centos6.5 ifconfig 显示为eth2,配置文件只有eth0
  13. vue中的this.$router.replace()和.push()和.go()的区别解析
  14. R数据分析:随机截距交叉滞后RI-CLPM与传统交叉滞后CLPM
  15. CF833D Red-Black Cobweb 点分治、树状数组
  16. 安卓修改电池容量教程_安卓手机端修改电池电量图标的教程
  17. 从租售比看中国房价的合理性
  18. 时间序列-ARIMA
  19. 5s进水不开机怎么办 苹果5s进水后无法开机的维修方法
  20. [C++]深复制与浅复制

热门文章

  1. 微博登录设备有python_Python模拟微博登陆,亲测有效
  2. 菜鸟在线教你用Unity3D开发VR版的Hello World
  3. NOI / 2.1基本算法之枚举 7213:垃圾炸弹
  4. 通俗易懂的带你解读inout双向端口【Verilog高级教程】
  5. 计算机毕业设计Java校园教务系统登录(源码+系统+mysql数据库+Lw文档)
  6. 角色架構安全性與 Web Services Enhancements 2.0 的相互應用
  7. MOS管进阶部分,那些你不了解的MOS管知识
  8. vsnprintf 变参
  9. c语言二维数组作用,C语言二维数组知识点介绍
  10. JS实现动画之setTimeout、setInterval和requestAnimationFrame