vue的生命周期

143 阅读3分钟

生命周期

  • 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
  • 生命周期如图:

image.png

beforeCreate() :创建之前

  • 会在实例初始化完成、props 解析之后、data()computed 等选项处理之前立即调用。
  • 无法访问data中的状态和methods中的方法

created() :创建完成

  • 当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
  • 可以访问data中的状态和methods中的方法

beforeMount() :挂载前

  • 当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。
  • 可以访问data中的状态和methods中的方法,但是无法访问到 dom 中的内容

mounted() :挂载完成

  • 所有同步子组件都已经被挂载。这个钩子通常用于执行需要访问组件所渲染的 DOM 树相关的副作用
  • 可以访问data中的状态和methods中的方法,可以访问到 dom 中的内容

beforeUpdate() :更新前

  • 这个钩子可以用来在 Vue 更新 DOM 之前访问 DOM 状态。在这个钩子中更改状态也是安全的。
  • 能访问到更改后的元素,
  • 但是无法获取最新的dom,因为此时dom还未更新(在使用v-if时,dom还未被创建)

updated() :更新完成

  • 这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的。
  • 如果你需要在某个特定的状态更改后访问更新后的 DOM,请使用 nextTick() 作为替代。

beforeUnmount() :卸载前

  • 当这个钩子被调用时,组件实例依然还保有全部的功能。

unmounted() :卸载完成

  • 在一个组件实例被卸载之后调用。
  • 可以在这里做清除工作
  • 卸载发生在v-if为false时

父组件

<template>
  <h1>App</h1>
  <!-- 创建和挂载 -->
  <div class="content">
    <p>我是内容:</p>
    {{ myname }}
  </div>
  <hr />

  <!-- 更新 -->
  <button @click="isShow = !isShow">显示 / 隐藏</button>
  <p class="name" v-if="isShow">{{ myname }}</p>
  <hr />

  <!-- 卸载 -->
  <button @click="isChild = !isChild">开启 / 关闭</button>
  <Child v-if="isChild" />
</template>

<script>
import Child from "./Child.vue";
export default {
  components: {
    Child,
  },
  data() {
    return {
      myname: "caoxinmei",
      isShow: false,
      isChild: true,
    };
  },
  beforeCreate() {
    /* 
    创建前
        无法访问data和methods中的内容 
    */
    console.log("beforeCreate", this.myname); // undefined
  },
  created() {
    /* 
    创建后
        能访问data和methods中的内容
        在这里可以做初始化的操作,把复杂的data数据进行拆分
     */
    console.log("created", this.myname);
  },
  beforeMount() {
    /* 
    挂载前
        能访问data和methods中的内容,但是无法访问到 dom 中的内容
     */
    let oCon = document.querySelector(".content"); // nullo
    console.log("beforeMount", this.myname, oCon);
  },

  mounted() {
    /* 
    挂载完成
        能访问data、methods和 dom 中的内容
        可以做:
            此时可以操作dom中的内容,可以做一些与dom有关的初始化操作
            初始化轮播、echarts、setInterval、ajax 
    */
    let oCon = document.querySelector(".content");
    console.log("mounted", this.myname, oCon);
  },
  beforeUpdate() {
    /* 
    更新前
        能访问到更改后的元素,
        但是无法获取最新的dom,因为此时dom还未更新(在使用v-if时,dom还未被创建)
    */
    let oName = document.querySelector(".name");
    console.log("beforeUpdate", this.myname, oName);
  },
  //   更新完成
  updated() {
    /* 
    更新完成:
        能访问到更改后的元素,并且能获取到最新的dom
    */
    let oName = document.querySelector(".name");
    console.log("updated", this.myname, oName);
  },
};
</script>

子组件

<template>
  <div>
    <h2>我是子组件</h2>
  </div>
</template>

<script>
export default {
  // 在挂载完成后,设置一个定时器
  mounted() {
    this.timer = setInterval(() => {
      console.log(11);
    }, 200);
  },

  beforeUnmount() {
    /* 
    卸载前:
    */
    console.log("beforeUnmount");
  },
  //   可以看到在卸载完成这个组件后,定时器还是在运行
  //   可以在卸载完成后,清除定时器
  unmounted() {
    /* 
    卸载完成:
        这里可以做清理工作,比如:
            清除定时器、取消订阅消息、清除事件监听
    */
    console.log("unmounted");
    clearInterval(this.timer);
  },
};
</script>