Vue生命周期指的是Vue实例或Vue组件实例在创建时经历的一系列初始化步骤。

在这个过程中Vue为用户提供了一些可供用户自定义的函数,即生命周期回调函数。这些函数又称为生命周期函数或生命周期钩子。


生命周期图示

Vue组件的生命周期图示如下:

Vue.js 生命周期

下图是尚硅谷天禹所给的有关Vue生命周期的解释:

Vue.js 生命周期解释


生命周期函数

生命周期函数本质是Vue在生命周期过程中的某些关键时刻帮用户调用的一些特殊名称的函数。

生命周期函数的名字不可更改,但函数的具体内容由程序员根据需求编写。

生命周期函数中的this指向的是当前的Vue实例或当前组件的实例对象。

下方代码演示了Vue生命周期函数:

<div id="app">
  <!-- <h2 v-text="num"></h2> -->
  <h2>Current Number:{{num}}</h2>
  <button @click="add">Number+1</button>
  <button @click="bye">销毁Vue实例</button>
</div>
<script type="text/javascript">
  new Vue({
    el: "#app",
    data: {
      num: 1,
    },
    methods: {
      add() {
        console.log('add.');
        this.num++
      },
      bye() {
        console.log('Bye.');
        /**
         * vm.$destroy():
         * 销毁vm,清理它与其它实例的连接,解绑全部指令及事件监听器(自定义事件)
         * 但是在销毁之前vm对页面所作的改变,在销毁之后依旧呈现在页面中
         * 销毁了vm之后仅仅意味着没有vm来管理页面的修改了
         * 在某些Vue版本(如 2.6.12)中,销毁了vm后事件绑定的函数依然可以被调用
         */
        this.$destroy()
      },
    },
    watch: {
      num() {
        console.log('The [num] was updated.');
      },
    },

    /**
     * 生命周期和事件初始化完成
     */
    beforeCreate() {
      console.log('beforeCreate.');
      console.log(this);  // Vue 实例中还没有 _data
      debugger  // 断点
    },
    /**
     * 数据监测和数据代理初始化完成
     */
    created() {
      console.log('created.');
      console.log(this);
      debugger
    },

    /**
     * 模板解析完成,已生成虚拟DOM
     */
    beforeMount() {
      console.log('beforeMount.');
      console.log(this);
      document.getElementsByName('h2')[0].innerText('Hello')
      debugger
    },
    /**
     * 虚拟DOM已经转为真实DOM插入页面
     */
    mounted() {
      console.log('mounted.');
      console.log(this);
      console.log(this.$el);
      console.log(this.$el instanceof HTMLElement);
      debugger
    },

    /**
     * data 更新后重新编译页面之前
     */
    beforeUpdate() {
      console.log('beforeUpdate.');
      console.log(this.num);
      debugger
    },
    /**
     * data 更新之后页面已经编译完成
     */
    updated() {
      console.log('updated.');
      console.log(this.num);
      debugger
    },

    /**
     * vm被销毁之前
     */
    beforeDestroy() {
      console.log('beforeDestroy.');
      this.add()  // 此时已经不能对页面做出更改了
      console.log(this.num);
      debugger
    },
    /**
     * vm已经被销毁
     */
    destroyed() {
      console.log('destroyed.');
    },
  });
</script>

可以看出在Vue的生命周期过程中共有8个(4对)钩子函数。


创建流程

  1. beforeCreate():生命周期和事件初始化完成时执行。

    数据代理和数据监测还未开始。

  2. created():数据监测和数据代理初始化完成时执行。

创建指的是数据代理和数据监测被创建。

注:在watch中,配置了immediate:truewatch是在Init Reactivity阶段(也就是Init Options API中)第1次执行handler()方法。

也就是说,配置了immediate:truewatch,其handler()beforeCreate()之后created()之前进行第1次执行


挂载流程

  1. beforeMount():模板解析完成。

    此时已生成虚拟DOM,但页面还未经过编译,展示的是模板的原内容。在此对DOM的操作,最终都不奏效

  2. mounted():虚拟DOM已经转为真实DOM插入页面时执行。

    此时页面中呈现的是已经Vue编译过的DOM,对DOM的操作有效(使用Vue的过程尽可能避免操作DOM)。

    一般在此时进行如下等初始化操作:

    • 开启定时器
    • 发送网络请求
    • 订阅消息
    • 绑定自定义事件

数据更新流程

  1. beforeUpdate():数据更新后重新编译页面之前执行。

    数据是修改之后的,但页面还未重新编译,仍是旧的(更新之前的内容)。

  2. updated():数据更新之后执行。

    此时页面已经编译完成。数据在更新之后,页面已经完成了编译,与数据同步。此时已经完成了Model => View的更新。


销毁流程

  1. beforeDestory()vm被销毁之前(还未销毁)执行。

    此时vm中所有的datamethods、指令等等都处于可用状态。

    一般在此阶段执行如下等收尾操作:

    • 关闭定时器
    • 取消订阅消息
    • 解绑自定义事件

    此时所有对数据的修改不会再触发更新(不能再对页面做出更改)。

  2. destroyed()vm被销毁之后(销毁完毕)执行。

    此时vm中所有的监听器、子组件和(自定义)事件监听器被移除。

    一般很少在这个钩子里做处理。

销毁与vm.$destroy()相关。只有对vm(Vue实例)调用vm.$destroy()后,vm才会开始进行销毁流程。

vm.$destroy()

  • 销毁vm,清理它与其它实例的连接,解绑全部指令及事件监听器(自定义事件)。
  • 在销毁之前(调用vm.$destroy()之前),vm对页面所作的改变,在销毁之后依旧呈现在页面中。
  • 销毁了vm之后仅仅意味着没有vm来管理页面的修改了。
  • 在某些Vue版本(如 2.6.12)中,销毁了vm后事件绑定的函数依然可以被调用。即原生DOM事件依然有效。

在大多数场景中,不应该调用vm.$destroy()。最好使用v-ifv-for指令,以数据驱动的方式控制子组件的生命周期。