前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue onBeforeUnmount 清理 定时器 事件监听 泄漏
VuVue侦听与生命周期

Vue 组件卸载时,定时器和全局事件应该在哪个钩子清理?

Vue 会停止组件自己的响应式效果,却不知道第三方资源应该调用哪个关闭方法。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#侦听与生命周期
先看核心答案读代码示例
理解线索

把资源创建和销毁成对设计

  1. 建立资源保存计时器、监听函数、观察器或连接引用
  2. 卸载前关闭停止新事件进入并释放第三方资源
  3. 卸载后确认组件效果和子树已结束,不再访问实例节点

清理应处理重复调用,避免手动关闭与组件卸载两条路径造成二次异常。

核心回答

先记住这个答案

组件手动创建的定时器、window 事件、ResizeObserver、连接或第三方实例,应在卸载流程中显式释放。onBeforeUnmount 运行时组件仍然完整可用,适合需要读取实例状态并发出关闭动作;onUnmounted 运行时子组件与关联响应式效果已经停止,适合确认结束。许多资源在任一处都能释放,关键是注册与取消使用同一引用、覆盖提前失败,并让清理幂等。setup 中同步创建的 watch 会自动停止,但其回调建立的外部资源仍需登记清理。

  • 外部资源需要显式调用自己的释放接口
  • beforeUnmount 时组件仍然可用
  • 注册和移除必须保存同一函数或实例引用

内存泄漏之外还有行为泄漏

全局键盘监听忘记移除,不仅保留闭包和组件数据,还会让用户离开页面后继续触发快捷键。定时器可能重复请求,重新进入页面又添加一份,最终表现为动作执行多次。

排查时不能只看浏览器内存曲线。记录活动监听、连接与定时任务的数量,在反复挂载和卸载后应回到基线;同时验证卸载后模拟事件不会继续改变旧状态。

使用同一个函数引用移除监听

下例由调用方传入类似 EventTarget 的对象,mounted 时添加固定 handler,beforeUnmount 时用同一引用移除。把匿名函数分别写在 add 和 remove 中会得到两个对象,无法取消原监听。

示例让 handler 只递增普通计数,以便在自定义事件源中验证卸载后不再调用。真实浏览器实现还要确保事件类型、capture 等选项在添加和移除时匹配。

挂载与卸载使用同一监听引用TypeScript
import { h, onBeforeUnmount, onMounted } from 'vue'

function makeListenerProbe(target: Pick<EventTarget, 'addEventListener' | 'removeEventListener'>) {
  const state = { calls: 0 }
  return {
    state,
    component: {
      setup() {
        const handler = () => { state.calls++ }
        onMounted(() => target.addEventListener('change', handler))
        onBeforeUnmount(() => target.removeEventListener('change', handler))
        return () => h('span', String(state.calls))
      }
    }
  }
}

挂载组件后触发 change 会让 calls 加一;卸载后再次触发保持不变。工厂保存状态仅用于验证,产品状态若需要更新视图应使用 ref,并避免在组件结束后继续接收事件。

清理异步资源要考虑等待

关闭 WebSocket 可以同步发起,但服务端确认可能稍后到达;组件卸载钩子不应被当作等待所有关闭 Promise 的事务。先让本地回调失效、移除引用,再由日志或应用级关闭流程观察异步结果。

如果资源在异步初始化完成前组件就卸载,清理钩子当时可能还没有句柄。需要取消初始化或设置 disposed 标记,资源迟到后立即关闭,避免只写 optionalHandle?.close 而留下卸载后创建窗口。

回答前,多想一步

容易答错的地方

add 和 remove 分别使用匿名函数
两个看似相同的箭头函数并不是同一引用,remove 无法匹配已注册监听。先声明 handler,再在创建和清理两处复用,并保存必要选项。
认为自动停止 watch 会关闭所有任务
Vue 能停止观察者本身,但无法猜测回调启动的请求、第三方订阅或工作器如何结束。把这些取消动作登记在 watcher 清理或组件作用域清理中。
试着用自己的话回答

面试官还会怎么问?

应该选择 onBeforeUnmount 还是 onUnmounted?

需要在组件仍完整可用时读取引用或主动断开,使用 before;只做无需组件状态的最终释放,两者通常都可。团队更应统一资源所有权和幂等规则,而非死记唯一钩子。

KeepAlive 切走时会执行卸载吗?

缓存组件进入 deactivated 状态而不是普通卸载,若资源只应在可见时活动,要在 deactivated 暂停、activated 恢复;最终从缓存移除时再完成永久释放。

如何测试监听真的移除了?

使用可计数的事件源,挂载后确认监听数为一并能触发,卸载后确认回到零且再次触发不改变状态。再循环挂载多次,验证数量不会逐次累积。

从一道题,走向一组知识

把知识连起来

侦听与生命周期

Vue KeepAlive 为什么要用 onActivated 和 onDeactivated?

缓存组件切换需要暂停恢复,而不是只等待永久卸载。

侦听与生命周期

Vue onScopeDispose 在什么时机执行,适合清理哪些资源?

组合式函数可把释放动作登记到当前 effect scope。

侦听与生命周期

Vue 中如何停止 watch 或 watchEffect,停止后还会执行吗?

单个 watcher 提前结束时也会运行其已登记的副作用清理。

参考资料

  • Vue:onBeforeUnmount
  • Vue:onUnmounted

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 内存泄漏之外还有行为泄漏
  3. 使用同一个函数引用移除监听
  4. 清理异步资源要考虑等待
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑