vue3 watchEffect 自动卸载时机引发的疑问?-灵析社区

云卿山手

**个人背景:** 一枚前端开发 **问题场景:** 在开发的时候,有这样一个需求,有一个类似于进度条进度的数据 **mockData** ,A,B,页面都需要使用到这个数据,所以我选择把它放到全局的 pinia 里管理。并且在 A 页面用户点击按钮的时候,开始观察 mockData 的变化。(我这里选择使用了 wathcEffect) **场景模拟:** 1. 这是 mockData import { ref } from "vue"; const count = ref(0); //全局的进度条 mockData setInterval(() => { count.value++; // 不停 +1 console.log("count.value", count.value); }, 1000); export { count }; 2. 这是 A 页面的代码, B 页面没有什么重要的代码,只是作为一个路由跳转到的界面而已。(无需关系 B 页面做了什么) import { watchEffect } from "vue"; import { useRouter } from "vue-router"; import { count } from "@/count++"; const router = useRouter(); function test() { watchEffect(() => { const a = count.value; console.log("a", a); if (a === 10) { router.replace("/red"); } }); } click 3. 我进到 A 页面点击按钮,开始观察 mockData 的变化,当 a 到10的时候,页面跳转 到 B 页面。 ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241120/a92a522388c02aa5a61165d92c57c8e9.png) 4. 此时错误的预期发生了,页面到了 B ,但是对 a 的打印还在输出。 ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241120/0d8656b13133117d473843f9dcbfe666.png) 5. 我将 watchEffect 移出函数,则一切正常 ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241120/b620b1e0e701dac52b4043e2c05fce10.png) **问题:** 为什么会导致这样的现象呢?为什么页面都消失了,但是对于 a 的watch 还没停止。

阅读量:15

点赞量:0

问AI
首先你这里存在一个误解,"watchEffect" 不是和页面产生的绑定关系,而是传入 "watchEffect" 的回调函数与函数中用到的"响应式状态"产生的绑定关系,也就是所谓的依赖搜集 关键在这里,你定义了一个无法回收的 "setInterval",页面拉起来后将一直运行,而你 A -> B 只是单纯的前端路由跳转,本质还是同一个页面,所以不会影响 "setInterval" 持续运行, "setInterval" 没有被清理掉,"count" 就会一直变,继而 "watchEffect" 的回调也会一直执行 setInterval(() => { count.value++; // 不停 +1 console.log("count.value", count.value); }, 1000); 要解决这个现象么在跳转路由前清理掉 "setInterval",要么 stop 掉 "watchEffect", 但按照你这种用法,两个都应该清理,因为这里 "watchEffect" 的回调引用的是一个全局的响应式状态,不手动 stop 掉的话,跳转路由后该回调函数所占用的内存是无法被回收的 另外,还有一个细节,同步的 "watchEffect" 会挂在组件实例上,随组件销毁而销毁;而异步创建的需要手动清理,具体看官方文档 "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241120/2fb73a699d50991ddc71484d601dfa94.png)