专栏首页前端之旅Vue 生命周期与钩子函数

Vue 生命周期与钩子函数

1.Vue 生命周期

Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载 dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

2.Vue 生命周期函数

Vue 的生命周期共有 8 个阶段,即创建前/后, 载入前/后,更新前/后,销毁前/销毁后,并对应地有很多钩子函数,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

3.Vue 生命周期图

Vue 官网图片

4. Vue 生命周期进程

根据上面的图来分析 Vue 生命周期的进程:

1.实例化 Vue(组件)对象,确定 this 指向 Vue 实例

2.初始化事件(events)和生命周期(cycle)

3.beforeCreate 函数

这一阶段,虽然 Vue 对象已经创建,但是它的属性还没有绑定,诸如 data、computed 这些属性还没有赋值。所以 $el,$data 以及 message 都是 undefined。

4.初始化注入和响应

这一阶段,Vue 对象的属性注入绑定,完成属性赋值。

5.Created 函数

这一阶段可以访问数据,但是还没有挂载 dom,不能访问到 $el。因为这个原因,此时改变数据不会触发 updated 函数。

6.两次判断

这个阶段会进行两次判断:

  • 判断对象是否有 el 选项 如果有则继续向下编译;如果没有则停止编译,也即停止生命周期,直到在实例上再次调用 vm.$mount(el) 才会继续向下编译
  • 判断 el 是否有 template 模板 如果有则将该模板编译为渲染函数,最后渲染出来;如果没有则直接调用 $el 的 outerHTML 进行渲染。另外,如果 Vue 对象中有渲染函数(render function),则它会优先于 template 进行渲染。 综上,优先级是:render function > template > outerHTML

7.beforeMount 函数

这个阶段,this.$el 有值,但是数据还没有挂载到页面上,`{{}}` 还没有被替换

8.用vue对象的数据(属性)替换模板中的内容

9.mounted 函数

模板编译完成,数据挂载完毕,页面上已经能够看到正确的数据了。

10.beforeUpdate 函数

数据更新后首先触发该函数,但更新的只是数据,innerHTML 尚未更新

11.虚拟 dom 重新渲染并打补丁

12.updated 函数

这一阶段,innerHTML 已经得到更新。

PS:这里解释一个问题。在 beforeUpdate 函数中访问 this.$el,innerHTML 时得到的是旧数据,这是正常的;但访问 this.$el 的时候,得到的却是新数据,这是因为:1.console.log 是异步的,我们期望打印的时候是打印那一刻的快照,但实际上它不能做到这一点,所以在后面点击展开 this.$el 的内容时,实际上只能访问到最新更新的对象;2.this.$el 保存的是对象的引用。

13.beforeDestroy 函数

这一阶段,实例还没有销毁,仍然完全可用

14.销毁实例

14.destroyed 函数

实例销毁之后调用该函数,使 Vue 实例指示的所有东西解绑定,所有的监听器被移除,所有的子实例销毁。

5.通过控制台观察生命周期的过程

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
     <p>{{ message }}</p>
</div>
<script type="text/javascript">    
var app = new Vue({
  el: '#app',
  data: {
      message : "Vue" 
  },
  beforeCreate: function () {
     console.group('beforeCreate 创建前状态===============》');
     console.log("%c%s", "color:red" , "el     : " + this.$el); 
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message);  
    },
  created: function () {
     console.group('created 创建完毕状态===============》');
     console.log("%c%s", "color:red","el     : " + this.$el); 
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  beforeMount: function () {
     console.group('beforeMount 挂载前状态===============》');
     console.log("%c%s", "color:red","el     : "); console.log(this.$el);    
     console.log("%c%s", "color:red","data   : " + this.$data);  
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  mounted: function () {
     console.group('mounted 挂载结束状态===============》');
     console.log("%c%s", "color:red","el     : "); console.log(this.$el);    
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  beforeUpdate: function () {
     console.group('beforeUpdate 更新前状态===============》');
     console.log("%c%s", "color:red","el     : "); console.log(this.$el);     
     console.log("%c%s", "color:red","el.outerHTML   : " + this.$el.outerHTML); 
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  updated: function () {
     console.group('updated 更新完成状态===============》');
     console.log("%c%s", "color:red","el     : "); console.log(this.$el);    
     console.log("%c%s", "color:red","el.outerHTML   : " + this.$el.outerHTML); 
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  beforeDestroy: function () {
     console.group('beforeDestroy 销毁前状态===============》');
     console.log("%c%s", "color:red","el     : " + this.$el);
     console.log(this.$el);    
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message); 
  },
  destroyed: function () {
     console.group('destroyed 销毁完成状态===============》');
     console.log("%c%s", "color:red","el     : " + this.$el);
     console.log(this.$el);  
     console.log("%c%s", "color:red","data   : " + this.$data); 
     console.log("%c%s", "color:red","message: " + this.message);
  }
});
</script>
</body>
</html>

第一次渲染,可以在控制台看到:

之后手动修改 message 的值为“Vue2”,可以在控制台看到:

这里注意之前提到的 log 异步的问题,看 outerHTML 可以知道 beforeUpdate 的时候视图实际上还没有重新渲染。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • AJAX 与跨域通信(一):AJAX 与同源策略

    在远古时代,如果浏览器需要从服务器请求资源,其交互模式为 “客户端发出请求 -> 服务端接收请求并返回相应 HTML 文档 -> 页面刷新,客户端加载新的 HT...

    Chor
  • 「译」利用 JavaScript 复制文本到剪贴板

    一个小小的诀窍。实现主题的复制代码功能时,思路刚好和这篇文章差不多,不过这篇文章的代码要更加合理。

    Chor
  • 记两道关于事件循环的题

    这里的关键其实是搞清楚 await async2() 做了什么事情。我以为在 async1 内部,async2 被调用之后,就会继续往后执行,因此是先打印 as...

    Chor
  • Vue笔记:生命周期和钩子函数

    在使用vue一个多礼拜后,感觉现在还停留在初级阶段,虽然知道怎么和后端做数据交互,但是对于mounted这个挂载还不是很清楚的。放大之,对vue的生命周期不甚了...

    朝雨忆轻尘
  • vue生命周期

    Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命...

    跟着阿笨一起玩NET
  • VUE生命周期

    每一个vue组件都是有生命周期的,通过其生命周期,我们可以在其中初始化数据和销毁数据的操作。每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是v...

    无邪Z

扫码关注云+社区

领取腾讯云代金券