VUE的生命周期是啥?

Author Avatar
EmptinessBoy 4月 20, 2021
  • 在其它设备中阅读本文章

对于 VUE.js 的生命周期,VUE 的官方文档灰常贴心的为我们准备了一个长长的图片,和那么一小段文字注解。不过说实话第一次看的时候我也是一头雾水的。

VUE 的生命周期,就是一个 VUE 项目从初始化到销毁的全部过程。标准的 VUE.js 项目拥有,creat,mount,update 和 destory 四个生命周期,而每个生命周期都可以分为 before 和 after 两个不同的阶段。因此 VUE.js 一共有如下 8 个生命周期的钩子函数。

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

通过生命周期钩子的函数,我们可以在 vue 实例的不同阶段添加自己的代码。

演示代码

这里我引用了网上一位 dalao 分享的演示代码(Author:fsrookie / 代码出处https://segmentfault.com/a/1190000011381906)。

在这段示例中,我们将从 cdn 引入 vue.js 的相关代码,并在vue 每个生命周期钩子里向控制台打印当前的 周期,el 和 data,方便我们观测 vue 生命周期的不同阶段的状态。

<!DOCTYPE html>
<html lang="cn">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>vue生命周期</title>
  <script src="https:[email protected]"></script>
</head>
<body>
  <div id="app">
    <h1>{{message}}</h1>
  </div>
</body>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      message: 'Vue的生命周期'
    },
    beforeCreate: function() {
      console.group('------beforeCreate创建前状态------');
      console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
      console.log("%c%s", "color:red","data   : " + this.$data); //undefined 
      console.log("%c%s", "color:red","message: " + this.message) 
    },
    created: function() {
      console.group('------created创建完毕状态------');
      console.log("%c%s", "color:red","el     : " + this.$el); //undefined
      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     : " + (this.$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     : " + this.$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     : " + this.$el.innerHTML);
      console.log(this.$el.innerHTML);   
      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     : " + this.$el.innerHTML);
      console.log(this.$el.innerHTML); 
      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>
</html>

CREAT

image-20210420090248526

CREAT 可以分为 beforeCreated 和 created 两个阶段:

beforeCreated

此时,组件实例刚刚创建,还未进行数据观测和事件配置。此时在 beforeCreate 中拿不到任何数据。

通过控制台的输出我们也可以看到,因为 el 和 data 并未初始化,所以 methods, data, computed 等方法和数据都是不能使用的。

image-20210420093013045

created

created 将在实例创建完后立即被调用。在 beforeCreated 到 created 的阶段,vue 实例已经完成了数据观测,属性和方法的计算,但尚未开始挂载。因此可以从控制台看到此时的的 data 已经和数据进行了绑定。

image-20210420093639117

MOUNT

image-20210420094531840

MOUNT 可以分为 beforeMount 和 mounted 两个阶段:

beforeMount

检查是否存在 el 属性,存在的话进行渲染 dom 操作(此时的 dom 还是虚拟 dom,并没有挂载到真实 dom 树上去),此时可以调用根节点 el 但不能调用真实节点 refs。

image-20210420095805324

此时 vue 实例还会判断 vue 对象中有没有 template 选项,如果 vue 实例对象中有template参数选项,则将其作为模板编译。如果没有 template 选项,则将外部 HTML 作为模板编译。

template 中的模板优先级要高于 outer HTML 的优先级。

增加 template 选项代码:

var vm = new Vue({
    el: '#app',
    template: "<h1>{{message +'这是在template中的'}}</h1>", //在vue配置项中修改的
    data: {
      message: 'Vue的生命周期'
    }
)

mounted

在 mounted 之前 h1 中还是通过 进行占位的,因为此时还有挂在到页面上,还是 JavaScript 中的虚拟 DOM 形式存在的。在 mounted 之后可以看到 h1 的内容发生了变化,此时的 dom 为真实 dom。

image-20210420100637359

但是 mounted 执行完毕后,并没有挂载所有的子组件,如果需要等待整个视图都渲染完毕,可以使用 vm.$nextTick。

mounted(){
    this.$nextTick(()=>{
        // 执行代码
    })
}

UPDATE

image-20210420102141594

当 vue 发现 data 中的数据发生了改变,会触发对应组件的重新渲染,先后调用 beforeUpdateupdated 钩子函数。

beforeUpdate

此钩子在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。(也就是说还有什么更改可以在这阶段一并处理,最终只重新渲染一次dom,不重复渲染了)

这里,我们通过修改 vm.message 进行测试,可以看到目前 dom 还没有更新。

image-20210420102456243

updated

此时 dom 元素已经被更新了,可以对 dom 进行相关操作。(大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。此外该钩子在服务器端渲染期间不被调用)

image-20210420102721191

DESTORY

image-20210420103605227

DESTORY 可以分为 beforeDestory 和 destoryed 两个阶段:

beforeDestory

这个钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的 dom 事件。

image-20210420104217468

destoryed

钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。(该钩子在服务器端渲染期间不被调用)

image-20210420104300481

vue 的生命周期钩子虽然只有简单的 8 个,但要理清楚每个钩子的作用以及区别还是需要一丢丢时间的。重要的是要学会如何正确的使用生命周期钩子来执行自己想要的功能。(想到我自己以前的一个 vue 页面中设置了定时器,导致跳转其他页面后,定时器还在工作,那时我捣鼓了半天都没能清掉这个定时器,就是因为没掌握 vue 生命周期才导致的。

尾图4

This blog is under a CC BY-NC-ND 4.0 Unported License
本文链接:https://coding.emptinessboy.com/2021/04/VUE%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%98%AF%E5%95%A5%EF%BC%9F/