Vue 3组合式函数中调用生命周期钩子必须在setup或<script setup>内同步执行,依赖当前组件实例;封装时需确保函数被setup调用,并直接导入使用onMounted等钩子。

在 Vue 3 组合式函数(Composable)中调用生命周期钩子,核心原则是:必须确保钩子在组件的 setup 执行期间同步注册,且只能在有活跃组件实例的上下文中使用。直接在普通 JavaScript 函数里调用会报错——因为钩子依赖当前组件的生命周期上下文。
必须在 setup 或 script setup 中调用
生命周期钩子如 onMounted、onUnmounted 等不是全局函数,它们内部依赖 Vue 的“当前活动实例”(currentInstance)。这个实例只在组件的 setup() 执行时存在。
- ✅ 正确:在
<script setup>或setup() { ... }内部直接导入并使用 - ❌ 错误:写在一个纯工具函数里,再从 setup 外部调用它
在自定义组合式函数中安全使用
如果想把生命周期逻辑封装进可复用的组合式函数(比如 useFetch、useScrollPosition),需满足两个条件:
- 该函数必须被组件的
setup调用(即运行在组件上下文中) - 在函数内部,直接导入并调用生命周期钩子,Vue 会自动绑定到当前组件
例如:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
✔️ 正确封装示例:import { onMounted, onUnmounted } from 'vue'
export function useTimer(callback) {
let timer = null
onMounted(() => {
timer = setInterval(callback, 1000)
})
onUnmounted(() => {
if (timer) clearInterval(timer)
})
}
在组件中使用时,只要在 <script setup> 中调用它即可:
<script setup>
import { useTimer } from './composables/useTimer'
useTimer(() => console.log('tick'))
</script>
不能脱离组件上下文单独执行
以下写法会导致警告或失效:
- 在
setTimeout、异步回调、事件处理器中调用onMounted - 在非 setup 函数(如普通
function init() {})中调用生命周期钩子 - 在服务端渲染(SSR)环境中,
onMounted和onUnmounted不会执行(它们仅客户端有效)
常见误区提醒
- 不要试图“延迟注册”钩子:生命周期钩子必须同步出现在 setup 执行流中,不能包裹在条件判断或异步操作后
-
避免重复注册:同一个钩子多次调用(如两次
onMounted)会注册多个回调,都生效,但要注意清理逻辑是否匹配 -
子组件挂载时机不可控:在父组件的
onMounted中访问子组件 DOM 元素(如ref)可能为空——建议用nextTick或监听子组件暴露的onMounted事件

















