Vue 3 用 effectScope 收口组合式函数的副作用,避免内存泄漏
test12026-10-092 次阅读
副作用散落的问题
把逻辑抽成组合式函数时,常常在里面建了 ref、computed、watch,甚至绑定了 window 的事件监听。组件卸载时 Vue 会自动停止模板里创建的副作用,但组合式函数内部手动创建的 watch、事件监听如果在函数返回后没人 stop,就会悄悄泄漏。一个函数用得越多,越难保证每个调用方都记得清理。
effectScope 一键接管
effectScope 把一组副作用圈进同一个作用域,调用 stop() 就能一次性全部停止,不需要逐个数着 stop 哪一个。
import { effectScope, ref, watch, onScopeDispose } from 'vue';
function useOnlineStatus() {
const scope = effectScope();
const online = ref(navigator.onLine);
scope.run(() => {
const handler = () => { online.value = navigator.onLine };
window.addEventListener('online', handler);
window.addEventListener('offline', handler);
// 作用域 stop 时自动执行
onScopeDispose(() => {
window.removeEventListener('online', handler);
window.removeEventListener('offline', handler);
});
});
onScopeDispose(() => scope.stop());
return online;
}
在组件里自动回收
组件内直接调用组合式函数时,Vue 会在组件卸载时自动 stop 当前组件的作用域,因此函数内部通过 effectScope 创建的副作用也会跟着一起清理,调用方什么都不用做。
import { ref } from 'vue';
export function useSearch(keyword: Ref<string>) {
const scope = effectScope();
const result = ref<string[]>([]);
scope.run(() => {
watch(keyword, (kw) => {
result.value = kw ? [`命中: ${kw}`] : [];
}, { immediate: true });
});
onScopeDispose(() => scope.stop());
return result;
}
关键心智模型
- effectScope 适合封装"会创建多个响应式副作用"的可复用逻辑,把清理收口到一处。
- onScopeDispose 注册在当前作用域 stop 时执行,常用于解绑事件、清除定时器等。
- 组件内使用会随组件卸载自动 stop;在组件外(如独立模块、测试、库)使用要手动 stop。
- 不要为了单个 watch 就上 effectScope,单个副作用用自身的 stop 即可。
T
test1
文章作者
副作用散落的问题 把逻辑抽成组合式函数时,常常在里面建了 ref、computed、watch,甚至绑定了 windo...
- 分类
- 技术
- 发布时间
- 2026-10-09
- 字数
- 约 1487 字
- 阅读
- 2 次
