watch使用不当,轻则内存占用飙升,重则页面卡顿、响应延迟。尤其在监听大型嵌套对象时,滥用deep: true会触发全量遍历,造成严重的性能损耗。
根本问题在于:只要对象内部任意层级的属性发生变化,无论是否相关,都会执行回调。这种“无差别监听”在高频更新场景下极易拖垮应用。
方案一:精准监听,直击目标字段
避免监听整个对象,改为追踪具体路径:
watch(
() => state.config.user.settings.theme,
(newTheme) => {
applyTheme(newTheme);
}
)
仅当目标属性变化时触发,彻底规避深度遍历开销。
方案二:借助computed收敛依赖
将需监听的多个字段聚合为一个计算状态:
const userInfo = computed(() => ({
username: state.profile.name,
level: state.profile.level
}))
watch(
userInfo,
({ username, level }) => {
updateBadge(username, level);
}
)
虽然监听仍需deep,但依赖范围被严格限定,极大降低遍历成本。
方案三:多源监听,显式声明依赖
使用数组形式同时监听多个响应式路径:
watch(
[
() => form.data.password,
() => form.data.confirmPassword
],
([pwd, confirm]) => {
validatePassword(pwd, confirm);
}
)
无需开启deep,无递归遍历,性能最优,适合关联性弱但需统一处理的字段。
总结
| 策略 | 优势 | 注意点 |
|---|---|---|
| 精准监听 | 零遍历,最高性能 | 仅适用于单一路径 |
| computed聚合 | 逻辑集中,依赖明确 | 需配合deep,但范围可控 |
| 多源监听 | 语法清晰,无需deep | 适合多个独立字段 |
核心原则:拒绝全量扫描,监听粒度越细越好。deep: true不是银弹,盲目使用只会让应用越来越慢。
浙公网安备 33010602011771号