Vue 生命周期钩子

Vue 组件生命周期钩子及父子组件执行顺序

问题

Vue 组件有哪些生命周期钩子?父子组件嵌套时,钩子的执行顺序是什么?

解答

生命周期钩子一览

阶段Vue 2Vue 3
创建前beforeCreatebeforeCreate
创建后createdcreated
挂载前beforeMountbeforeMount
挂载后mountedmounted
更新前beforeUpdatebeforeUpdate
更新后updatedupdated
销毁前beforeDestroybeforeUnmount
销毁后destroyedunmounted

各钩子的用途

export default {
  beforeCreate() {
    // 实例初始化后,data 和 methods 还不可用
    // 用途:插件初始化
  },
  
  created() {
    // data 和 methods 已可用,DOM 还未生成
    // 用途:发起 API 请求、初始化数据
  },
  
  beforeMount() {
    // 模板编译完成,即将挂载到 DOM
  },
  
  mounted() {
    // DOM 已挂载完成
    // 用途:操作 DOM、初始化第三方库
  },
  
  beforeUpdate() {
    // 数据变化后,DOM 更新前
    // 用途:获取更新前的 DOM 状态
  },
  
  updated() {
    // DOM 已更新完成
    // 注意:避免在此修改数据,可能导致无限循环
  },
  
  beforeUnmount() {
    // 组件即将销毁
    // 用途:清理定时器、取消订阅
  },
  
  unmounted() {
    // 组件已销毁
  }
}

父子组件执行顺序

<!-- Parent.vue -->
<template>
  <div>
    <Child />
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  components: { Child },
  beforeCreate() { console.log('父 beforeCreate') },
  created() { console.log('父 created') },
  beforeMount() { console.log('父 beforeMount') },
  mounted() { console.log('父 mounted') },
  beforeUpdate() { console.log('父 beforeUpdate') },
  updated() { console.log('父 updated') },
  beforeUnmount() { console.log('父 beforeUnmount') },
  unmounted() { console.log('父 unmounted') }
}
</script>
<!-- Child.vue -->
<template>
  <div>子组件</div>
</template>

<script>
export default {
  beforeCreate() { console.log('子 beforeCreate') },
  created() { console.log('子 created') },
  beforeMount() { console.log('子 beforeMount') },
  mounted() { console.log('子 mounted') },
  beforeUpdate() { console.log('子 beforeUpdate') },
  updated() { console.log('子 updated') },
  beforeUnmount() { console.log('子 beforeUnmount') },
  unmounted() { console.log('子 unmounted') }
}
</script>

挂载阶段输出:

父 beforeCreate
父 created
父 beforeMount
子 beforeCreate
子 created
子 beforeMount
子 mounted
父 mounted

更新阶段输出:

父 beforeUpdate
子 beforeUpdate
子 updated
父 updated

销毁阶段输出:

父 beforeUnmount
子 beforeUnmount
子 unmounted
父 unmounted

执行顺序图示

挂载:父创建 → 父挂载前 → 子创建 → 子挂载 → 父挂载完成

更新:父更新前 → 子更新前 → 子更新后 → 父更新后

销毁:父销毁前 → 子销毁前 → 子销毁后 → 父销毁后

Vue 3 Composition API

import { 
  onBeforeMount, 
  onMounted, 
  onBeforeUpdate, 
  onUpdated,
  onBeforeUnmount,
  onUnmounted 
} from 'vue'

export default {
  setup() {
    // setup 本身相当于 beforeCreate + created
    
    onBeforeMount(() => {
      console.log('挂载前')
    })
    
    onMounted(() => {
      console.log('挂载后')
    })
    
    onBeforeUpdate(() => {
      console.log('更新前')
    })
    
    onUpdated(() => {
      console.log('更新后')
    })
    
    onBeforeUnmount(() => {
      console.log('销毁前')
    })
    
    onUnmounted(() => {
      console.log('销毁后')
    })
  }
}

关键点

  • 挂载顺序:父组件先创建,等子组件全部挂载完成后,父组件才算挂载完成
  • 销毁顺序:父组件先触发销毁,等子组件销毁完成后,父组件才算销毁完成
  • created vs mounted:created 用于数据初始化,mounted 用于 DOM 操作
  • 清理工作:在 beforeUnmount 中清理定时器、事件监听、取消请求
  • 避免死循环:不要在 updated 中修改响应式数据