生命周期简绍
-
beforeCreate:在实例初始化之后,数据观测之前,data 和 $el 不可用。
-
created:在实例创建完成后被立即调用,data可用,$el不可用。
-
beforeMount:在挂载DOM开始之前被调用,data可用,$el不可用。
-
mounted:组件被调用并被挂载到实例上的回调,data 和 $el 可用。
-
beforeDestroy:实例销毁之前调用,data 和 $el 可用。
-
destroyed:Vue 实例销毁后调用,data可用,$el不可用。
-
beforeUpdate:数据更新时调用,发生在虚拟DOM打补丁前。适合在更新之前访问现有的DOM,比如移除已添加的事件监听。
-
updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
activated:keep-alive 组件激活时调用。
-
deactivated:keep-alive 组件停用时调用。
-
errorCaptured:当捕获一个来自子孙组件的错误时被调用。此钩子可以返回 false 以阻止该错误继续向上传播。
本文主要以 beforeCreate、created、beforeMount、mounted、beforeDestroy、destroyed 这几个钩子为主,分析多组件之间生命周期的触发顺序。
单个组件
单个组件触发顺序如下:
beforeCreate
created
beforeMount
mounted
beforeDestroy
destroyed
父子关系
// page
<A></A>
// 组件A
<B></B>
// 组件B
<C></C>
触发顺序如下:
A beforeCreate
A created
A beforeMount
B beforeCreate
B created
B beforeMount
C beforeCreate
C created
C beforeMount
C mounted
B mounted
A mounted
A beforeDestroy
B beforeDestroy
C beforeDestroy
C destroyed
B destroyed
A destroyed
兄弟关系
// page
<A></A>
<B></B>
<C></C>
触发顺序如下:
A beforeCreate
A created
A beforeMount
B beforeCreate
B created
B beforeMount
C beforeCreate
C created
C beforeMount
A mounted
B mounted
C mounted
A beforeDestroy
A destroyed
B beforeDestroy
B destroyed
C beforeDestroy
C destroyed
页面之间跳转
把 A、B 组件分别挂载到两个路由下,从 A 跳转到 B 看一下生命周期是怎么触发的(或者用 v-if v-else 切换两个组件的显示)。
// page
<button @click="status = false">Btn</button>
<A v-if="status"></A>
<B v-else></B>
A beforeCreate
A created
A beforeMount
A mounted
B beforeCreate
B created
B beforeMount
A beforeDestroy
A destroyed
B mounted
这个比较有意思,为什么不是先把A销毁再加载B呢,而是B渲染完成才销毁A,主要是为了避免长时间白屏。
总结
-
父子组件之间加载时,会先从父到子按 beforeCreate created beforeMount 触发,然后从子到父触发 mounted。
-
父子组件之间销毁时,会先从父到子触发 beforeDestroy,再从子到父触发 destroyed。
-
兄弟组件之间加载时,会依据组件渲染顺序从上到下按 beforeCreate created beforeMount 组件单独触发,然后按顺序触发 mounted。
-
兄弟组件之间销毁时,依据组件渲染顺序从上到下按 beforeDestroy destroyed 触发。
-
组件切换显示时,先执行被显示组件的 beforeCreate created beforeMount,再执行被销毁组件的 beforeDestroy destroyed,最后执行被显示组件的 mounted。(这么做是为了减少白屏时间)