浅析Vue-生命周期钩子

121 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第六天, 点击查看活动详情

Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

Vue-生命周期

这是人的生命周期

image-20210111193143574.png Vue的生命周期

一个组件从 创建 到 销毁 的整个过程就是生命周期 image-20210511152835915.png

vue-钩子函数

作用: 特定的时间点,执行特定的操作

场景: 组件创建完毕后,可以在created 生命周期函数中发起Ajax 请求,从而初始化 data 数据

分类: 4大阶段8个方法

  • 初始化
  • 挂载
  • 更新
  • 销毁
阶段方法名方法名
初始化beforeCreatecreated
挂载beforeMountmounted
更新beforeUpdateupdated
销毁beforeDestroydestroyed

[官网文档](cn.vuejs.org/v2/guide/in…

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

Day03.png

vue-初始化阶段

  1. new Vue() – Vue实例化(组件也是一个小的Vue实例)

  2. Init Events & Lifecycle – 初始化事件和生命周期函数

  3. beforeCreate – 生命周期钩子函数被执行

  4. Init injections&reactivity – Vue内部添加data和methods等

  5. created – 生命周期钩子函数被执行, 实例创建

  6. 接下来是编译模板阶段 –开始分析

  7. Has el option? – 是否有el选项 – 检查要挂到哪里

    • 没有. 调用$mount()方法

    • 有, 继续检查template选项

image-20210511153050932.png

挂载阶段

1.template选项检查

有 - 编译template返回render渲染函数

例如:

但是: 因为Vue脚手架环境使用webpack+vue-template-compiler包, 进行模板编译转换后运行, 所以vue.js里只有运行时的代码, 所以这么写在脚手架环境会报错

所以: 脚手架环境, 直接写的是render函数方式进行渲染

new Vue({
  template: `<div>我是div啊</div>`
}).$mount('#app')

无 – 编译el选项对应标签作为template(要渲染的模板)

例如:

<div id="app">
    <p>{{ msg }}</p>
</div>

2.虚拟DOM挂载成真实DOM之前

3.beforeMount – 生命周期钩子函数被执行

4.Create … – 把虚拟DOM和渲染的数据一并挂到真实DOM上

5.真实DOM挂载完毕

6.mounted – 生命周期钩子函数被执行

image.png components/Life.vue - 创建一个文件

<template>
  <div>
      <p>学习生命周期 - 看控制台打印</p>
      <p id="myP">{{ msg }}</p>
  </div>
</template>

<script>
export default {
    // ...省略其他代码
    
    // 二. 挂载
    // 真实DOM挂载之前
    // 场景: 预处理data, 不会触发updated钩子函数
    beforeMount(){
        console.log("beforeMount -- 执行");
        console.log(document.getElementById("myP")); // null

        this.msg = "重新值"
    },
    // 真实DOM挂载以后
    // 场景: 挂载后真实DOM
    mounted(){
        console.log("mounted -- 执行");
        console.log(document.getElementById("myP")); // p
    }
}
</script>

Vue-更新阶段

  1. 当data里数据改变, 更新DOM之前

  2. beforeUpdate – 生命周期钩子函数被执行

  3. Virtual DOM…… – 虚拟DOM重新渲染, 打补丁到真实DOM

  4. updated – 生命周期钩子函数被执行

  5. 当有data数据改变 – 重复这个循环

image.png components/Life.vue - 创建一个文件

准备ul+li循环, 按钮添加元素, 触发data改变->导致更新周期开始

<template>
  <div>
      <p>学习生命周期 - 看控制台打印</p>
      <p id="myP">{{ msg }}</p>
      <ul id="myUL">
          <li v-for="(val, index) in arr" :key="index">
              {{ val }}
          </li>
      </ul>
      <button @click="arr.push(1000)">点击末尾加值</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            msg: "hello, Vue",
            arr: [5, 8, 2, 1]
        }
    },
    // ...省略其他代码

    // 三. 更新
    // 前提: data数据改变才执行
    // 更新之前
    beforeUpdate(){
        console.log("beforeUpdate -- 执行");
        console.log(document.querySelectorAll("#myUL>li")[4]); // undefined
    },
    // 更新之后
    // 场景: 获取更新后的真实DOM
    updated(){
        console.log("updated -- 执行");
        console.log(document.querySelectorAll("#myUL>li")[4]); // li
    }
}
</script>

Vue-销毁阶段

  1. 当$destroy()被调用 – 比如组件DOM被移除(例v-if)

  2. beforeDestroy – 生命周期钩子函数被执行

  3. 拆卸数据监视器、子组件和事件侦听器

  4. 实例销毁后, 最后触发一个钩子函数

  5. destroyed – 生命周期钩子函数被执行

image.png

  • 一般在beforeDestroy/destroyed里做什么?
    • 手动消除计时器/定时器/全局事件

数据请求在created和mounted的区别

created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成。mounted是在页面dom节点渲染完毕之后就立刻执行的。触发时机上created是比mounted要更早的;两者相同点:

都能拿到实例对象的属性和方法。讨论这和问题的本质就是触发时机,放在mounted请求有可能导致页面闪动(页面dom结构已经生成),但如果在页面加载前完成则不会出现此情况,建议:放在created生命周期当中。