大家好,我是小墨,射手座,三十多年从未打过架,斗地主逃跑率99% 。代码写得比字多,bug 修得比头发快 ,秉持“能跑就是好代码”的哲学 。日常和前端打交道,代码写得比注释多,希望和大家多多交流!🤝
开发中,我们其实会经常遇到这样的场景:用户的某个操作改变了数据,页面需要立刻感知并做出反应——可能是更新界面、调用接口,或者执行一段复杂的逻辑。Vue 3 中的watch干这个的,它能让我们精细控制数据响应的能力。
但我们什么时候用deep?immediate又是干什么的?如何优雅地处理异步操作避免内存泄漏?
本期带大家彻底搞懂watch!我们先来看一张图,快速了解watch的核心:
1. 洞察单一数据的变动:基础监听
这是watch最直接的用途——盯住一个响应式数据的变化。
痛点解决:当应用中某个关键数据(如用户输入、配置项)改变时,需要自动执行特定逻辑,而不是手动在各处检查。
上面的代码中,watch侦听searchTerm。用户每次输入导致searchTerm变化,回调函数都会执行,并根据新旧值更新提示信息searchHint。
2. 同时侦听多个数据源
如果一个操作依赖于多个数据的共同变化,watch也能轻松应对。
痛点解决:当多个条件同时满足或任一条件改变时才触发某个复杂计算或UI更新,避免编写繁琐的多个独立监听器或复杂的computed依赖。
这里,watch同时关注firstName、lastName和termsAccepted。任何一个数据的变动都会触发回调,用于判断表单是否可提交。
3. 侦听对象内部的细微变化 (deep: true)
默认的watch只看“表面”,如果你想深入对象内部,就需要deep: true。
痛点解决:监听一个复杂对象时,其深层嵌套的属性发生变化,默认的watch无法感知。deep: true解决了这个问题,让你不再错过任何细微改动。
开启deep: true后,userPreferences对象内任何层级的属性变化都会被捕捉。小墨提醒:深度侦听会递归遍历对象,对于非常庞大的对象,可能会有性能开销,务必谨慎使用。
4. 创建侦听器时立即执行回调 (immediate: true)
如果希望watch的回调在侦听器创建时就马上执行一次。
痛点解决:组件初始化时,就需要根据某个数据的初始值执行一次逻辑(如API请求、状态设置),而不是等到它第一次“变化”后才执行。
下面是一个简单的图示对比immediate的效果:
有了immediate: true,组件一挂载,就会根据初始的entityId执行一次数据加载逻辑。
5. :数据变化后的异步任务处理
watch是处理异步操作的得力助手,比如根据用户输入延迟请求API。
痛点解决:用户输入时,若每次按键都触发API请求会造成浪费。watch结合防抖/节流可以优化此场景,并在请求过程中管理加载状态。
下面是watch处理异步请求的一个典型流程:
这里通过setTimeout实现了一个简易的防抖 (debounce) 效果,避免用户每次按键都触发校验。
6. 适时停止侦听
watch返回一个函数,调用它即可停止该侦听。这在组件卸载时非常重要。
痛点解决:如果watch侦听的数据源生命周期比组件长,或者在某些条件下不再需要监听,不及时停止会导致内存泄漏或不必要的性能消耗。
在onBeforeUnmount钩子中调用watch返回的stopWatch函数,确保组件销毁时,相关的侦听逻辑也一并清理,这是Vue开发中非常重要的好习惯。