vue.js $ watch对象数组

Far*_*her 32 vue.js

mounted: function() {
  this.$watch('things', function(){console.log('a thing changed')}, true);
}
Run Code Online (Sandbox Code Playgroud)

things 是一个对象数组 [{foo:1}, {foo:2}]

$watch检测添加或删除对象的时间,但不检测对象上的值是否更改.我怎样才能做到这一点?

Pan*_*lis 61

您应该传递一个对象而不是布尔值options,因此:

mounted: function () {
  this.$watch('things', function () {
    console.log('a thing changed')
  }, {deep:true})
}
Run Code Online (Sandbox Code Playgroud)

或者你可以vue像这样将观察者设置到实例中:

new Vue({
  ...
  watch: {
    things: {
      handler: function (val, oldVal) {
        console.log('a thing changed')
      },
      deep: true
    }
  },
  ...
})
Run Code Online (Sandbox Code Playgroud)

[试玩]

  • `ready`在vue 2.0中将名称更改为`mounted`! (3认同)

小智 7

如果有人需要获取阵列中已更改的项目,请检查:

JSFiddle示例

帖子示例代码:

new Vue({
  ...
  watch: {
    things: {
      handler: function (val, oldVal) {
        var vm = this;
        val.filter( function( p, idx ) {
            return Object.keys(p).some( function( prop ) {
                var diff = p[prop] !== vm.clonethings[idx][prop];
                if(diff) {
                    p.changed = true;                        
                }
            })
        });
      },
      deep: true
    }
  },
  ...
})
Run Code Online (Sandbox Code Playgroud)

  • 在每次更新时差异整个数组似乎有点过分.我想知道是否有办法让Vue直接告诉我哪个元素已更新... (17认同)

Smo*_*kie 7

您可以使用$watch('arr.0', () => {})或独立观察数组或字典中的每个元素的变化$watch('dict.keyName', () => {})

来自https://vuejs.org/v2/api/#vm-watch

注意:当改变(而不是替换)对象或数组时,旧值将与新值相同,因为它们引用相同的对象/数组。Vue 不会保留 pre-mutate 值的副本。

但是,您可以独立迭代 dict/array 和 $watch 每个项目。IE。$watch('foo.bar')- 这会监视对象 'foo' 的属性 'bar' 的变化。

在这个例子中,我们观察 arr_of_numbers 中的所有项目,以及 arr_of_objects 中所有项目的 'foo' 属性:

mounted() {
        this.arr_of_numbers.forEach( (index, val) => {
            this.$watch(['arr_of_numbers', index].join('.'), (newVal, oldVal) => {
                console.info("arr_of_numbers", newVal, oldVal);
            });
        });

        for (let index in this.arr_of_objects) {
            this.$watch(['arr_of_objects', index, 'foo'].join('.'), (newVal, oldVal) => {
                console.info("arr_of_objects", this.arr_of_objects[index], newVal, oldVal);
            });
        }

    },
    data() {
        return {
            arr_of_numbers: [0, 1, 2, 3],
            arr_of_objects: [{foo: 'foo'}, {foo:'bar'}]
        }
    }
Run Code Online (Sandbox Code Playgroud)


Aur*_*ert 5

有一种更简单的方法可以在没有深度观察的情况下观察数组的项目:使用计算值

{
  el: "#app",
  data () {
    return {
      list: [{a: 0}],
      calls: 0,
      changes: 0,
    }
  },
  computed: {
    copy () { return this.list.slice() },
  },
  watch: {
    copy (a, b) {
      this.calls ++
      if (a.length !== b.length) return this.onChange()
      for (let i=0; i<a.length; i++) {
        if (a[i] !== b[i]) return this.onChange()
      }
    }
  },
  methods: {
    onChange () {
      console.log('change')
      this.changes ++
    },
    addItem () { this.list.push({a: 0}) },
    incrItem (i) { this.list[i].a ++ },
    removeItem(i) { this.list.splice(i, 1) }
  }
}
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/aurelienlt89/x2kca57e/15/

这个想法是构建一个计算值copy,该值正是我们想要检查的。计算值很神奇,并且只将观察者放在实际读取的属性上(这里是listread in的项目list.slice())。copy观察者中的检查实际上几乎没有用(可能除了奇怪的极端情况)因为计算值已经非常精确。