为何在Pinia仓库的Vue监听器中必须指定deep: true?
问题解答
首先得明确Vue文档里说的「直接对响应式对象调用watch()时隐式创建深度监听器」,指的是监听reactive创建的响应式对象的场景,比如:
const obj = reactive({ bar: 1 }) watch(obj, () => console.log('变更触发')) // 此时修改obj.bar会触发监听,无需deep
而你的代码里,foo是用ref包裹的对象,这和上面的场景本质不同:
ref的响应式是针对.value的引用变化的,也就是说只有当你替换整个.value(比如foo.value = { bar: 2 })时,watch(foo)才会触发。- 当你只修改
.value内部的属性(比如foo.value.bar++),这属于对象内部的嵌套变更,watch(foo)默认只会监听.value的引用是否改变,不会深入到对象内部,所以必须手动加上{ deep: true }才能监听到这类变更。
至于storeToRefs()的作用,它只是保证你从Pinia store里解构出来的foo依然是一个响应式的ref,不会丢失响应式关联,但它改变不了Vue watch的监听规则——watch监听ref时,默认还是只关注其.value的引用变化,而非内部对象的属性变化。
如果不想用deep: true,除了你提到的替换整个.value的方式,还有两种更精准的方案:
- 直接监听对象的具体属性:
watch(() => foo.value.bar, (newVal) => { console.log('bar变更了:', newVal) })
- 把store里的
foo改成reactive对象(如果适合你的业务场景):
// store.js const foo = reactive({ bar: 1 }) watch(foo, () => console.log({ foo })) // 此时修改foo.bar会自动触发监听,无需deep
内容的提问来源于stack exchange,提问作者Minh Nghĩa
相关产品推荐
相关产品推荐

