Skip to content

Watch 手动清理 自动清理 ​

本节目标:理解“Watch 手动清理 自动清理”的核心思路,并能把它用于实际开发或面试表达。 结论先说在你这段代码的场景里,用 this.unwatchQuote 保存清理函数是有必要的,Vue 不会帮你自动清理。

为什么有时候会“自动清理”? 在 Vue 3 里:

  • watch(...) 会返回一个 停止函数(stop handle);
  • 只有在「有作用域」里创建的 watch,才会在作用域销毁时自动停止,比如:
    • 在组件的 setup() 里同步调用的 watch
    • 在 effectScope 里创建的 watch

这类情况是 “跟着组件生命周期走的监听”,组件卸载时 Vue 会帮你 stop。

你的这段代码属于哪种情况? 你的代码大概是这样的(简化): this.unwatchQuote = watch( () => this.socketStore.quoteTick, async () => { // ... K 线更新逻辑 ... }, { deep: true },) 结合你之前的上下文,这里有几个关键信息:

  1. 使用的是 this.xxx,而不是 ref / reactive,很大概率是在 class / 单独的 datafeed 类里,而不是组件 setup() 里直接写的;
  2. subscribeBars 这类方法一般是 在组件已经挂载后、甚至在各种回调/事件里再调用,此时已经不在 setup() 的“当前组件作用域”里了;
  3. 对于这种“组件外 / 作用域外”直接调用的 watch:
    • 它不会自动挂到某个组件的生命周期上;
    • 也就不会在组件卸载时自动清理。

所以,这个 watch 实际上变成了一个 全局挂着的响应式副作用:

  • 你不调用 this.unwatchQuote(),它就会一直存在;
  • 如果多次调用这一段代码(例如多次订阅 / 切换 symbol),就会叠加越来越多的 watcher,造成:
    • 回调被调用多次(重复更新 K 线);
    • 内存泄漏。

正确的用法建议1. 现在这种写法:保留 this.unwatchQuote 是对的 你现在保存清理函数,是为了在 “取消订阅 / 销毁 datafeed” 的时候主动 stop 这个 watcher,这一步是必须的。 典型写法: // 订阅时this.unwatchQuote = watch( () => this.socketStore.quoteTick, async () => { // ... 你的 K 线处理逻辑 ... }, { deep: true },) 在取消订阅 / 销毁实例时: // 在 unsubscribeBars 或销毁函数中// 主动取消监听,避免重复订阅和内存泄漏if (this.unwatchQuote) { this.unwatchQuote() this.unwatchQuote = undefined} 这个清理是 你自己负责的,Vue 不会在背后帮你做。

2. 只有在“跟组件绑死”的场景才可以不存 stop 函数 只有下面这种情况,才可以完全不关心 stop 函数,让 Vue 自动处理: export default { setup() { const state = reactive({ ... }) watch( () => state.xxx, (val) => { /* ... / }, ) // ⬆️ 这里是在 setup() 同步执行的 // 组件卸载时 Vue 会自动 stop 这个 watcher return { state } }} 或者在 effectScope 里: const scope = effectScope()scope.run(() => { watch(/ ... */)}) // 之后手动:scope.stop(),会把里面的 watch 全部清掉 而你现在这个 class / datafeed 对象 + this.xxx + 订阅/取消订阅 的模式,本质上是让 watch 跟着“订阅周期”而不是“组件周期”,所以就必须自己管理 stop。

小结

  • ✅ 在你这段代码里,保存 this.unwatchQuote 是有必要的;
  • ❌ 它不会因为组件销毁就自动清理(因为不在组件的作用域里创建);
  • ✅ 建议在 unsubscribeBars 或类似的清理函数里显式调用 this.unwatchQuote(),防止:
    • 重复订阅导致回调多次执行;
    • 内存泄漏。

如果你愿意,可以把 unsubscribeBars 那段也贴出来,我可以顺手帮你检查一下清理逻辑是不是完全闭环。 > 来自 <https://chatgpt.com/c/691adb9b-cbbc-832d-ab46-310d777d88de>

本站总访问 — 次