您的位置:

深入理解 Vue.js 的生命周期

一、生命周期的基础知识

Vue.js 的组件实例有一个完整的生命周期,包含多个阶段,每个阶段都有一个相应的钩子函数可以用于执行相应的操作。以下是 Vue.js 的生命周期图示:


        beforeCreate() {
            // 在实例初始化之后,数据观测(data observer)和 event/watcher 事件配置之前被调用。
        },
        created() {
            // 在实例创建完成后被立即调用
        },
        beforeMount() {
            // 在挂载开始之前被调用--即将模板编译成虚拟 DOM,并在将其渲染到 DOM 之前执行。
        },
        mounted() {
            // 实例挂载之后调用--将页面渲染完毕;
        },
        beforeUpdate() {
            // 数据更新时调用,但是并未渲染新数据,这里适合拿旧数据和准备更新的数据做对比操作。
        },
        updated() {
            // 在数据更新且模板重新渲染之后调用。  
        },
        beforeDestroy() {
            // 实例销毁之前调用--可以在这里进行解绑事件、销毁定时器、取消监听等等操作。
        },
        destroyed() {
            // 实例销毁之后调用--一般是清理计时器等东西。
        }

总之,Vue.js 的生命周期分为 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy 和 destroyed 等阶段,每个阶段都会有对应的钩子函数。

二、生命周期详解

1. beforeCreate 阶段

顾名思义,beforeCreate 阶段是在实例被创建之前调用的钩子函数,此时实例还没有被创建,所以也就无法访问到 data 和 methods 等实例属性。


      beforeCreate() {
          // 在实例被创建之前调用的钩子函数,此时实例还没有被创建,所以也就无法访问到 data 和 methods 等实例属性。
          // 此时定义的 data 属性、methods 等都不会生效。   
      }

2. created 阶段

created 阶段是在实例被创建之后调用的钩子函数,此时已经可以访问到 data 和 methods 等实例属性,但尚未生成真正的 DOM。


      created() {
          // 在实例创建完成后被立即调用,此时已经可以访问到 data 和 methods 等实例属性,但尚未生成真正的 DOM。
          // 比如可以在此时进行异步请求数据,操作数据等等。
      }

3. beforeMount 阶段

beforeMount 阶段是在模板编译成虚拟 DOM,并在将其渲染到 DOM 之前执行的钩子函数,此时已经可以访问到 DOM 树,但是还没有渲染出来。


      beforeMount() {
          // 此时已经可以访问到 DOM 树,但是还没有渲染出来,可以在此时进行一些数据的处理和初始化操作,但是不要对已处理过的数据进行多次操作。
      }

4. mounted 阶段

mounted 阶段是在模板被渲染成 DOM 之后调用的钩子函数,此时组件已经渲染完毕,DOM 中元素已经可以被访问到。


      mounted() {
          // 在模板被渲染成 DOM 之后调用,此时组件已经渲染完毕,DOM 中元素已经可以被访问到,常见使用场景比如向后台请求数据渲染页面,声明周期后,访问虚拟dom,可能需要等dom渲染完成才能访问,
          // 可通过 this.$nextTick() 等待模板渲染完毕之后执行操作。
      }

5. beforeUpdate 阶段

beforeUpdate 阶段是在数据更新时调用的钩子函数,但是此时并未渲染新数据,适合拿旧数据和准备更新的数据做对比操作。


      beforeUpdate() {
          // 数据更新时调用,但是并未渲染新数据,适合拿旧数据和准备更新的数据做对比操作。
          // 也可以在此时对数据进行修改,但是应该避免无限更新。
      }

6. updated 阶段

updated 阶段是在数据更新且模板重新渲染之后调用的钩子函数,此时可以访问新的 DOM 元素和更新之后的数据。


      updated() {
          // 在数据更新且模板重新渲染之后调用,可以访问新的 DOM 元素和更新之后的数据,但应该避免使用无限循环的操作,以免影响性能。
      }

7. beforeDestroy 阶段

beforeDestroy 阶段是在实例销毁之前调用的钩子函数,此时组件实例仍然可以访问。


      beforeDestroy() {
          // 在实例销毁之前调用,一般是解除事件监听、定时器等等。
      }

8. destroyed 阶段

destroyed 阶段是在实例销毁之后调用的钩子函数,此时组件实例已被完全销毁。


      destroyed() {
          // 实例销毁之后调用,一般用于清理计时器等。
      }

三、生命周期常见错误的解决方案

1. created 阶段使用 $refs

在 created 阶段使用 $refs 来操作 DOM 元素会报错,因为此时模板还未渲染成真正的 DOM,$refs 中并没有对应的 DOM 元素。

解决方案:在 mounted 阶段使用 $refs 操作 DOM 元素。

2. watch 与 computed 属性

watch 和 computed 是 Vue.js 中的两个重要的属性。watch 属性是用来监听数据变化的,而 computed 属性是用来计算数据的。在 watch 中计算数据或在 computed 中修改数据都是不允许的。

解决方案:在 computed 中计算数据,在 watch 中监听数据变化。

3. destroyed 钩子中的数据清理

在 destroyed 钩子中进行数据清理时,因为此时组件已经销毁,所以不能再访问组件中的 data 属性,清理操作也就无法进行。

解决方案一:在 beforeDestroy 钩子中进行数据清理。

解决方案二:建议采用 aminated 和 transition 进行操作,对组件进行卸载切换时,即使在组件已经被销毁的情况下,也可以通过 aminated 和 transition 组件实现一些操作。

四、总结

Vue.js 的生命周期是 Vue.js 组件中非常重要的一个部分。在 Vue.js 组件中,每个实例都有一个完整的生命周期,包含多个阶段,每个阶段都对应一个钩子函数,可以在不同的阶段中做出相应的操作。学好 Vue.js 的生命周期,可以更好地进行 Vue.js 应用程序的开发。