生命周期图示

vue生命周期_inner

生命周期钩子函数

状态 说明
beforeCreate(创建前) 组件实例更被创建,组件属性计算之前,数据对象 data 都为 undefined,未初始化。
created(创建后) 组件实例创建完成,属性已经绑定,数据对象 data 已存在,但 dom 未生成,$el 未存在
beforeMount(挂载前) vue 实例的$el 和 data 都已初始化,挂载之前为虚拟的 dom 节点,data.message 未替换
mounted(挂载后) vue 实例挂载完成,data.message 成功渲染。
beforeUpdate(更新前) 当 data 变化时,会触发 beforeUpdate 方法
updated(更新后) 当 data 变化时,会触发 updated 方法
beforeDestroy(销毁前) 组件销毁之前调用
destroyed(销毁后) 组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom 绑定,但 dom 结构依然存在

beforeCreate 创建前

在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

created 创建后

在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。

beforeMount 挂载前

在挂载开始之前被调用:相关的 render 函数首次被调用。

mounted 挂载后

实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。

注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick

beforeUpdate 更新前

数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

updated 更新后

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick

beforeDestroy 销毁前

实例销毁之前调用。在这一步,实例仍然完全可用。

destroyed 销毁后

实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

activated

被 keep-alive 缓存的组件激活时调用。

deactivated

被 keep-alive 缓存的组件停用时调用。

errorCaptured

2.5.0+ 新增

当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

生命周期解释

new Vue(options) 后

  1. 将用户提供的 options 与默认 options 合并,初始化 LifeCycle、Events、Render
  2. 触发 beforeCreate 钩子
  3. 初始化 Injections、State(包括初始化 props、methods、data(初始化 data 时 调用 Observer.observe 方法添加 Dep 依赖)、computed、watch)、Provide
  4. 触发 created 钩子
  5. 触发 beforeMount 钩子
  6. 对 vm 创建 Watcher 执行 updateComponent 方法,updateComponent方法调用 vm._render 方法生成 VNode,调用 vm._update 把 VNode 渲染成真实的 DOM
  7. 触发 mounted 钩子

数据 data 变化后

  1. 初始化 data 时创建的 Observer 通过 Dep 触发了 watcher.update() 方法,watcher.update() 调用 scheduler.queueWatcher() 调用 scheduler.flushSchedulerQueue(),尝试调用 watcher.run()
  2. 触发 beforeUpdate 钩子(之前已经注册了 Watcher.before)
  3. watcher 执行 watcher.run 方法,执行 watcher.get 方法,执行 watcher.getter 方法 即 updateComponent 方法,updateComponent 方法调用 vm._render 方法生成 VNode,调用 vm._update 把 VNode 渲染成真实的 DOM
  4. 再回到 scheduler.flushSchedulerQueue 方法,在所有的 watcher 执行完毕后,触发 updated 钩子

组件销毁时

patch.removeVnodes -> patch.invokeDestroyHook -> destroy -> vm.$destroy ->

  1. 调用 beforeDestroy 钩子
  2. 将自身从父组件中移除,移除 watchers
  3. 调用 destoryed 钩子
  4. 关闭所有实例监听器

Vue2 与Vue3的生命周期对比

Vue2 Vue3
beforeCreate(组件创建之前) setup(组件创建之前)
created(组件创建完成) setup(组件创建完成)
beforeMount(组件挂载之前) onBeforeMount(组件挂载之前)
mounted(组件挂载完成) onMounted(组件挂载完成)
beforeUpdate(数据更新,虚拟DOM打补丁之前) onBeforeUpdate(数据更新,虚拟DOM打补丁之前)
updated(数据更新,虚拟DOM渲染完成) onUpdated(数据更新,虚拟DOM渲染完成)
beforeDestroy(组件销毁之前) onBeforeUnmount(组件销毁之前)
destroyed(组件销毁之后) onUnmounted(组件销毁之后)

Vue 子组件和父组件执行顺序

加载渲染过程:

  1. 父组件 beforeCreate
  2. 父组件 created
  3. 父组件 beforeMount
  4. 子组件 beforeCreate
  5. 子组件 created
  6. 子组件 beforeMount
  7. 子组件 mounted
  8. 父组件 mounted

更新过程:

  1. 父组件 beforeUpdate
  2. 子组件 beforeUpdate
  3. 子组件 updated
  4. 父组件 updated

销毁过程:

  1. 父组件 beforeDestroy
  2. 子组件 beforeDestroy
  3. 子组件 destroyed
  4. 父组件 destoryed

异步请求放在哪个生命周期中

我们可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面加载时间,用户体验更好;
  • SSR不支持 beforeMount 、mounted 钩子函数,放在 created 中有助于保持一致性。