1. 前言

具体细节参考 Vue 官方文档 ,本章节会详细讲解到 Vue 的生命周期,理解了生命周期可以在不同的阶段更好的管理组件。

本章节会通过如下内容来讲解:

  • 生命周期基本概念
  • Vue 的生命周期
    • Vue 每个阶段做了哪些事情
    • Vue 代码详解

2. 生命周期

生命周期:就是从出生到死亡的一个过程,无论是在生活中还是在程序中都适用。

生命周期代表一个实体的整个生存过程,包括创建(出生)、更新(成长)、销毁(死亡)等阶段。


3. Vue2.X 生命周期

  1. 🤔思考:那 Vue 和人的生命周期有什么关系呢?

    • 创建(出生):created
    • 更新(成长):mounted
    • 销毁(死亡):destroyed
  2. 🤔思考:那 Vue 的生命周期可以抽象为那几个过程呢?

    可以分为四个阶段,八个过程,具体信息如下:

    在这个阶段,Vue 组件正在创造和准备自己,就像一个人从诞生到成长的过程。

    beforeCreate

    • 在组件实例初始化完成之后立即调用
    • vue 实例的挂载元素 $el数据对象 data 都为 undefined,还未初始化。
    • 类似在人出生前,家庭在准备迎接新成员,但孩子还没有呱呱坠地。

    create

    • 在组件实例处理完所有与状态相关的选项后调用。
    • vue 实例的 数据对象data有了,$el 还没有
    • 类似孩子出生后,已经成为一个个体,可以开始认识世界,但还没有参与到各种活动中。

    这个阶段类似于一个人的成长过程,Vue 组件与用户进行交互,更新状态,不断发展。

    beforeMount

    • 在组件被挂载到 DOM 之前调用。
    • vue 实例的 $eldata 都初始化了,但还是虚拟的 DOM 节点,具体的 data.filter 还未替换。
    • 类似孩子成长为学童,准备进入学校阶段,但尚未真正开始上课

    mounted

    • 在组件被挂载到 DOM 上后调用,这是初始化过程的最后一个阶段。
    • vue 实例挂载完成,data.filter 成功渲染。
    • 类似孩子已经进入学校,可以和同学互动,参加各种活动,融入社交圈。

    这个阶段类似于一个人在成长过程中的不断更新和变化,Vue 组件会根据数据的变化进行更新。

    beforeUpdate

    • 在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。
    • data 更新时触发,当虚拟DOM中的data发生改变时触发,此时虚拟DOM没有加载到页面上。
      页面上的数据不变,虚拟DOM中的数据改变。
    • 类似一个人在改变自己的日常习惯,但尚未完全转变为新状态。

    updated

    • 在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
    • data 更新时触发,虚拟DOM中的data发生改变页面上的data也发生改变(即新生成的虚拟DOM挂载上页面了)
    • 类似人已经适应了新的习惯,改变已经生效并完成更新。

    这个阶段类似于一个人的寿命终结阶段,Vue 组件准备完成最终的清理和结束。

    beforeDestroy

    • 在实例销毁之前被调用。可以进行清理工作,如取消定时器、解绑事件等。
    • 组件销毁时触发
    • 类似一个人在离世前,安排遗愿和做一些后事的准备。

    destroyed

    • 在实例销毁之后被调用。此时组件已经被完全销毁,事件监听和数据绑定都被解除。
    • 组件销毁时触发,vue 实例解除了事件监听以及和 DOM 绑定(无响应了),但 DOM节点依旧存在
    • 类似一个人已经离世,所有关联的事物都已经解除。
  3. 💡Vue 生命周期图解

    Vue 实例生命周期

  4. 🛠️代码实现

    假设 通过 计数器 按钮实现 Vue 的生命周期

    • HTML 模板和数据
    1
    2
    3
    4
    5
    6
    7
    <body>
    <div id="app">
    <p>计数器:{{ counter }}</p>
    <button @click="increment">增加</button>
    <button @click="destroy">销毁</button>
    </div>
    </body>
    • Vue 实例和数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <script>
    new Vue({
    el: '#app',
    data: {
    counter: 0
    },
    methods: {
    increment() {
    this.counter++;
    },
    destroy() {
    this.$destroy();
    }
    },
    beforeCreate() {
    console.log('beforeCreate: 实例正在创建中 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    created() {
    console.log('created: 实例已创建 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    beforeMount() {
    console.log('beforeMount: 在挂载到 DOM 之前 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    mounted() {
    console.log('mounted: 实例已挂载到 DOM ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    beforeUpdate() {
    console.log('beforeUpdate: 在更新数据之前 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    updated() {
    console.log('updated: 数据已更新 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    beforeDestroy() {
    console.log('beforeDestroy: 实例即将被销毁 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    },
    destroyed() {
    console.log('destroyed: 实例已被销毁 ==> 实例(this.counter):', this.counter, ',DOM节点:', this.$el);
    }
    });
    </script>
    • 结果

    动画