必须用 ondeactivated 而非 onunmounted,因为 keep-alive 缓存的组件失活时不卸载,onunmounted 不触发,而 ondeactivated 能精准捕获“离开视图但实例存活”的时机,是暂停轮询、动画、事件监听等副作用的唯一可靠入口。

图表组件在被缓存时若持续刷新(比如轮询接口、定时重绘、实时动画),不仅浪费资源,还可能引发内存泄漏或状态错乱。结合 onDeactivated 可以精准控制其“暂停”行为,确保组件失活时不执行无意义的更新。
为什么必须用 onDeactivated 而不是 onUnmounted?
onUnmounted 在组件真正销毁时才触发,但被 <keep-alive></keep-alive> 缓存的图表组件不会卸载——它只是从 DOM 中移除并进入缓存池。此时 onUnmounted 不会执行,而 onDeactivated 会准确捕获“离开视图但实例仍存活”的时机,是暂停逻辑的唯一可靠入口。
暂停轮询请求与定时器
常见图表依赖定时拉取最新数据,需在失活时停止轮询,避免后台无效请求:
- 使用
ref保存定时器 ID 或轮询控制器(如 AbortController) - 在
onDeactivated中清除定时器、调用abort()、取消 pending 请求 - 在
onActivated中恢复轮询(可选:带防抖或延迟重启)
示例:
import { ref, onActivated, onDeactivated } from 'vue'<br>const pollTimer = ref(null)<br>const abortController = ref(null)<br><br>function startPolling() {<br> abortController.value = new AbortController()<br> const fetchWithAbort = () => fetch('/api/chart-data', { signal: abortController.value.signal })<br> pollTimer.value = setInterval(() => fetchWithAbort().then(...), 5000)<br>}<br><br>function stopPolling() {<br> if (pollTimer.value) clearInterval(pollTimer.value)<br> if (abortController.value) abortController.value.abort()<br>}<br><br>onActivated(startPolling)<br>onDeactivated(stopPolling)
暂停 ECharts / Chart.js 等渲染动画与自动更新
像 ECharts 的 setOption({ animation: true }) 或 resize() 自动适配,若在失活状态下频繁调用,会导致性能抖动或报错(DOM 元素已不可见)。应:
- 监听
onDeactivated后调用chart.clear()或chart.dispose()(慎用 dispose,仅当确定不再复用时) - 更推荐:保留实例,暂停自动行为——设置
chart.setOption({ animation: false }),并手动控制resize和setOption的触发时机 - 配合
ref存储 chart 实例,在onDeactivated中取消 resize 监听器(如 window.addEventListener('resize', handler))
清理副作用与防止内存泄漏
图表组件常绑定事件、订阅 WebSocket、监听全局状态变化。这些若未清理,会在缓存期间持续响应,造成资源占用和逻辑干扰:
- 所有
addEventListener需配套removeEventListener - WebSocket 连接不宜关闭(除非业务要求),但应暂停
onmessage处理,或设标志位跳过失活期的消息 - Pinia / Vuex 订阅需在
onDeactivated中unsubscribe()
关键原则:只要你在 onActivated 中注册了什么,就要在 onDeactivated 中对称地注销它。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











