13

const app = {
  data(){
    return {
      form: {
        name: '',
        password: ''
      }
    } 
  },
  watch: {
    form: {
      handler(form, oldForm){
        console.log(form, oldForm);
      },
      deep: true
    } 
  }
}

Vue.createApp(app).mount('#app')
<script src="https://unpkg.com/vue@next"></script>
<main id="app">
  <form>
    <input v-model="form.name"/>
    <input v-model="form.password"/>
  </form>
</main>

I got a deep watcher for an object value, accroding to the document, it should get both the previous and current value of the object been watched.

But in this code, the new value and the old value returned by the deep watcher are always same. Why is that?

Thanks a lot for anyone help!

3 Answers 3

28

Ref: watch

Note: when mutating (rather than replacing) an Object or an Array and watch with deep option, the old value will be the same as new value because they reference the same Object/Array. Vue doesn't keep a copy of the pre-mutate value.

Sign up to request clarification or add additional context in comments.

1 Comment

key diffirence is use () => ({ ...form }), instead of () => form when define watch
19

Use setup to watch instead...

import {reactive} from 'vue'

setup() {
  const form = reactive({
      name: '',
      password: ''
  })

  watch(
        () => ({ ...form }),
        (newVal, oldVal) => {
            console.log('Form changed', newVal, oldVal)
        }
    )

  return {
    form
  }
}

2 Comments

How does this answer the question? Vue doesn't store the previous value anywhere, and as reactive() creates a reference type, once it's changed, the old value is gone forever... To get around this, you could use the toRef() Vue function for each item in the reactive object, but that kind of defeats the point of using reactive in the first place. I'm wondering why this has as many up-votes as it does?
@Jack_Hu It worked for non-deep watchers , I guess up-votes are from those.
0
const formTemplate = {
  name: '',
  password: ''
}

const app = {
  data() {
    return {
      form: {
        ...formTemplate
      },
      oldForm: {
        ...formTemplate
      },
    }
  },
  watch: {
    form: {
      handler(form) {
        console.log(form, this.oldForm);
        this.oldForm = JSON.parse(JSON.stringify(form))
      },
      deep: true
    }
  }
}

Vue.createApp(app).mount('#app')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.