标准答案
- Vue 的 watch、watchEffect、computed 等都会创建响应式 effect,组件 setup 中创建的 effect 通常会绑定到组件实例并在卸载时停止。
- effectScope 可以手动创建一个副作用作用域,把多个 watch、watchEffect 等集中收集起来。
- 调用 scope.stop() 后,作用域里的副作用会统一停止,适合 composable、插件或组件外状态模块管理清理。
- 如果响应式副作用创建在组件生命周期之外,就不能默认依赖组件卸载自动清理。
- effectScope 解决的是响应式副作用清理,不会自动取消 fetch、移除 DOM 事件或清掉定时器,这些仍然要单独处理。
题目解析
这道题要区分组件内自动清理和组件外手动清理。很多内存泄漏来自把 watch 放进全局模块后没有 stop。
Composable 如果只在组件 setup 中调用,通常可以依赖组件卸载;如果 composable 自己创建独立作用域或服务单例,就要暴露 stop 或内部管理生命周期。
effectScope 常和 onScopeDispose 配合使用,让调用者所在的作用域销毁时自动执行清理逻辑。
代码示例
下面的作用域可以统一停止内部 watchEffect。
TypeScript
const scope = effectScope()
scope.run(() => {
watchEffect(() => {
console.log(userStore.currentUser)
})
})
function disposeUserWatcher() {
scope.stop()
}常见误区
- 认为所有 watch 都会自动清理,忽略组件外创建的副作用。
- 用 effectScope 后以为网络请求、事件监听和定时器也会自动取消。
- 在 composable 中创建长期副作用,但没有暴露停止方式,也没有绑定当前 scope。