Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set watch deep: true, when data changes, val === oldval is true #2649

Closed
murphymeng opened this issue Apr 11, 2016 · 6 comments
Closed

set watch deep: true, when data changes, val === oldval is true #2649

murphymeng opened this issue Apr 11, 2016 · 6 comments

Comments

@murphymeng
Copy link

Vue.js version

1.0.16

Reproduction Link

Steps to reproduce

What is Expected?

What is actually happening?

@yyx990803
Copy link
Member

This is working as intended, because they are the same object.

@murphymeng
Copy link
Author

I have a very deep object and some key in it changes, is there any method I can get the changed key name, value and it's parent object? I don't need a whole object, thanks.

@phanan
Copy link
Member

phanan commented Apr 11, 2016

@murphymeng You may want to clone the original object and compare the clone with the modified object during watch callback. Also, please direct these questions to Gitter or the forum. Thanks.

@simplesmiler
Copy link
Member

@murphymeng you would have to:

  1. Avoid using v-model and .sync in favor of unidirectional data flow (:value="..." @change="...").
  2. Use immutable data (there's a useful library called object-path-immutable).
  3. Whenever watch triggered, run a comparison to figure out what has changed and what didn't.

@craigvantonder
Copy link

craigvantonder commented Dec 14, 2016

Wanted to share another solution that was provided by a user as an answer to my relative question on StackOverflow:

<div id="app">
  <input type="text" v-for="(person, index) in people" v-model="people[index].age" />
</div>

new Vue({
  methods: {
    setValue:function(){
      this.$data.oldPeople=_.cloneDeep(this.$data.people);
    },},
    mounted() {
      this.setValue();
    },
    el: '#app',
    data: {
      people: [
      {id: 0, name: 'Bob', age: 27},
      {id: 1, name: 'Frank', age: 32},
      {id: 2, name: 'Joe', age: 38}
      ],
      oldPeople:[]
    },
    watch: {
      people: {
        handler: function (after, before) {
        // Return the object that changed
        var vm=this;
        let changed = after.filter( function( p, idx ) {
          return Object.keys(p).some( function( prop ) {
           return p[prop] !== vm.$data.oldPeople[idx][prop];
         })
        })
        // Log it
        vm.setValue();
        console.log(changed)
      },
      deep: true,
    }
  }
})

With a note: "if you are adding or removing something from the original array, just call the vm.setValue() method again"

@AnonymousArthur
Copy link

@phanan Thank you! It's working. I think for very deep and complex object plus key occurrence uncertain, this way is much easier.
use Copy = Object.assign({},Target) to create a new object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants