Vue3生命周期执行顺序解析:
- 组合式API的setup()函数最先执行,其中注册的钩子函数(如onMounted)会先于选项式API的对应钩子(mounted)执行。
- 组合式API钩子是回调注册机制,按注册顺序执行,而选项式API仍按传统顺序执行。
开发时建议统一使用组合式API,避免混合使用导致意外行为。
尤其注意在setup()中无法访问DOM,需在钩子回调中操作。
Vue3生命周期

在 Vue 3 中,组合式 API 的 setup() 函数确实先于选项式 API 的生命周期钩子执行。
这是一个很重要的执行顺序规则。
执行顺序对比
1. 完整的生命周期执行顺序
vue
<script>
import { ref, onBeforeMount, onMounted } from 'vue'
export default {
setup() {
console.log('1. setup() 执行')
onBeforeMount(() => {
console.log('2. onBeforeMount() 执行')
})
onMounted(() => {
console.log('4. onMounted() 执行')
})
return {}
},
beforeCreate() {
console.log('3. beforeCreate() 执行')
},
created() {
console.log('5. created() 执行')
},
beforeMount() {
console.log('6. beforeMount() 执行')
},
mounted() {
console.log('7. mounted() 执行')
}
}
</script>
实际输出顺序:
1. setup() 执行
2. onBeforeMount() 执行
3. beforeCreate() 执行
4. onMounted() 执行
5. created() 执行
6. beforeMount() 执行
7. mounted() 执行
2. 混合使用时的详细顺序
vue
<script>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
console.log('1. setup()')
onBeforeMount(() => {
console.log('2. onBeforeMount')
})
onMounted(() => {
console.log('4. onMounted')
})
onBeforeUpdate(() => {
console.log('5. onBeforeUpdate')
})
onUpdated(() => {
console.log('7. onUpdated')
})
return {}
},
beforeCreate() {
console.log('3. beforeCreate')
},
created() {
console.log('6. created')
},
beforeMount() {
console.log('8. beforeMount')
},
mounted() {
console.log('9. mounted')
},
beforeUpdate() {
console.log('10. beforeUpdate')
},
updated() {
console.log('11. updated')
}
}
</script>
为什么会有这样的顺序?
Vue 3 内部执行流程:
-
setup()最先执行 - 这是组合式 API 的入口点 -
组合式 API 钩子注册 -
onBeforeMount()、onMounted()等在setup()中注册回调函数 -
选项式 API 钩子执行 - 按照传统的生命周期顺序执行
组合式 API 钩子 vs 选项式 API 钩子
javascript
// 组合式 API - 注册回调(在 setup() 中)
onBeforeMount(() => {}) // 只是注册,不立即执行
// 选项式 API - 直接定义方法
beforeMount() {} // 在相应阶段被 Vue 调用
重要注意事项
1. 在 <script setup> 中的情况
vue
<script setup>
import { onMounted } from 'vue'
// 在 <script setup> 中,代码在编译后都会放在 setup() 中
console.log('setup 中的代码最先执行')
onMounted(() => {
console.log('onMounted 回调')
})
</script>
<script>
// 普通 script 块中的代码会在 setup 之后执行
export default {
mounted() {
console.log('mounted 钩子')
}
}
</script>
2. 异步组件的特殊情况
vue
<script>
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() =>
import('./MyComponent.vue')
)
export default {
components: {
AsyncComponent
},
beforeCreate() {
// 会在异步组件加载前执行
}
}
</script>
3. 组合式 API 钩子的执行时机
vue
<script>
import { onMounted } from 'vue'
export default {
setup() {
// 注册顺序影响执行顺序
onMounted(() => {
console.log('第一个 onMounted')
})
onMounted(() => {
console.log('第二个 onMounted')
})
// 与选项式 API 混合时
return {}
},
mounted() {
console.log('选项式的 mounted')
// 会在所有 onMounted 回调之后执行
}
}
</script>
实际开发建议
推荐做法:
-
不要混合使用 - 尽量统一使用一种 API 风格
-
组合式 API 优先 - Vue 3 推荐使用组合式 API
-
迁移时注意顺序 - 从选项式迁移到组合式时,注意生命周期执行顺序的变化
常见问题:
vue
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
onMounted(() => {
console.log('DOM 已挂载,可以访问 DOM')
})
// ❌ 错误:在 setup() 中不能访问 DOM
// console.log(document.getElementById('app'))
return { count }
},
mounted() {
// ✅ 正确:在这里可以访问 DOM
console.log(this.$el)
}
}
</script>
总结
-
组合式 API 的
setup()函数最先执行 -
组合式 API 的生命周期钩子是注册回调函数,在对应阶段按注册顺序执行
-
选项式 API 的生命周期钩子按传统顺序执行,但在组合式 API 之后
-
了解这个顺序有助于避免在混合使用时出现意外行为