core icon indicating copy to clipboard operation
core copied to clipboard

watch deep options incorrect action

Open guda-art opened this issue 1 year ago • 5 comments

Vue version

3.5.6

Link to minimal reproduction

no

Steps to reproduce

1.case1

watch(
        [
          () => obj.value.number,
        ],
        () => {
          console.log('trigger')
        }
      );

2.case2

watch(
        [
          () => obj.value.number,
        ],
        () => {
          console.log('trigger')
        }, {
          deep: true
       }
      );

when use deep: true; number no change but other prop of obj change trigger still (Verified not to trigger when other change)

What is expected?

Consistent behavior

What is actually happening?

no Consistent behavior

System Info

Chrome 128.0.6613.137

Any additional comments?

No response

guda-art avatar Sep 20 '24 08:09 guda-art

Please provide a minimal reproduction.

edison1105 avatar Sep 20 '24 09:09 edison1105

Please provide a minimal reproduction.

deep: true will output trigger but false not

https://play.vuejs.org/#eNp9kstuwjAQRX9l5A1BQkFVu0pD1IdYtIu2aruruwhhCAHHtvwApCj/XscmEKSKrMZz79XMid2QRynjnUWSkFQXqpIGNBorM8qrWgploAGFq8k+N8UaWlgpUcPIBUaUF4JrA2KxgVnniRpu6wWqBG7aMeU+EVEOx+/nXAJEY5hlXTTe5cxiHJKTs+V3UAdzM8x3owXDmIkyGhlVlSWqkRva6+3k0r9ElAkYZXHg6cvxPeWUp9PA78jdwWAtWW7QnQDShTVGuOKhYFWxnVESBeoLYpJ5NZ0Gd0iub7Km8aDBCm2bTl2zmzeYQSbEaAe1qsp4owV31+H3p6QQtawYqndpKgdNSdKTUZIzJvavvtehHX+Zy6yx2P7T3+hD16PkQ6FGtUNKTprJVYkmyPOvNzy4+iTWYmmZc18RP9FdiO12DLYny5du7YHPb/viH1XFy289Pxjkuofq76b1fkrcE3u+gn5e9za+8znKW9L+Afdx4NY=

guda-art avatar Sep 22 '24 04:09 guda-art

This behavior is expected. According to the docs: https://vuejs.org/api/reactivity-core.html#watch

When using a getter source, the watcher only fires if the getter's return value has changed. If you want the callback to fire even on deep mutations, you need to explicitly force the watcher into deep mode with { deep: true }. Note in deep mode, the new value and the old will be the same object if the callback was triggered by a deep mutation:

In your case, { deep: true } causes the watcher to trigger when any property of the object changes, not just number.

jh-leong avatar Sep 22 '24 05:09 jh-leong

This behavior is expected. According to the docs: https://vuejs.org/api/reactivity-core.html#watch

When using a getter source, the watcher only fires if the getter's return value has changed. If you want the callback to fire even on deep mutations, you need to explicitly force the watcher into deep mode with { deep: true }. Note in deep mode, the new value and the old will be the same object if the callback was triggered by a deep mutation:

In your case, { deep: true } causes the watcher to trigger when any property of the object changes, not just number.

Firstly, my initial question was about whether to enable deep or not, and the behavior should be consistent (even if the value of other attributes changes when deep is enabled, it will not trigger the observer for that attribute). The link explains another issue, that is, when deep is enabled, if the attribute source that the getter depends on is replaced, even if the return value remains unchanged, the observer will still be triggered

guda-art avatar Sep 22 '24 08:09 guda-art

I was also surprised by this. I've always thought deep only cared about deep changes within the return value. It's a primitive here so I intuitively thought this would be identical.

One can wrap things with computed in these scenarios, of course, but it's not intuitive

andreasgangso avatar Dec 10 '25 17:12 andreasgangso