Vue观察器在创建同级属性时触发

时间:2020-03-19 23:31:11

标签: vue.js

我在观看vue时遇到问题。

如何解释这种行为:在{strong>创建 test.a属性时触发test.b上的观察者?

vm = new Vue({
  data: {
    test: { a: {}, c: {} }
  }
})
vm.$watch('test.a', () => {console.log('> test.a changed')})
vm.$watch('test.b', () => {console.log('> test.b changed')})
vm.$watch(() => vm.test.c, () => {console.log('> test.c changed')}, {deep: true})

setTimeout(() => {
  console.log('creating: test.b')
  Vue.set(vm.test, 'b', {})
}, 10)

setTimeout(() => {
  console.log('changing: test.b')
  vm.test.b = 1
}, 20)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>

编辑:

在现实世界中,我使用深度监视程序,但在正常深度监视程序类型中都观察到了这种行为。

创建新属性会触发所有喜欢的手表,并且在大多数情况下会触发普通手表。

2 个答案:

答案 0 :(得分:0)

Vue.set(vm.test, 'b', {})仅触发一次test中的更改。

   vm = new Vue({
      data: {
        test: { a: {}, b: {}}
      }
    })
    vm.$watch('test.a', () => {console.log('> test.a changed', vm.test)}, {deep: true})
    vm.$watch('test.b', () => {console.log('> test.b changed', vm.test.b)}, {deep: true})
    setTimeout(() => {
		Vue.set(vm.test, 'b', {name: 1})
    }, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

使用deep: truetest: {a: {}, b: {}}应该可以解决问题

答案 1 :(得分:0)

一种解决方案是使用返回嵌套对象的JSON的函数,而不是使用点分隔的路径:

vm.$watch(
  // The first function returns the JSON representation of the object
  () => JSON.stringify(vm.test.a),

  // Handler
  () => console.log('> test.a changed')
);

但是,对于vm.test.b(可能在运行时未定义),则需要使用新的null-coalescing operator ?? supported by some modern browsers

vm.$watch(
  // The first function returns the JSON representation of the object
  () => JSON.stringify(vm.test.b ?? {}),

  // Handler
  () => console.log('> test.a changed')
);

如果要向后兼容,可以使用更详细的检查,即:

vm.$watch(
  // The first function returns the JSON representation of the object
  () => JSON.stringify(vm.test.b === void 0 ? {} : vm.test.b),

  // Handler
  () => console.log('> test.a changed')
);

vm = new Vue({
  data: {
    test: {
      a: {}
    }
  }
})
vm.$watch(
  () => JSON.stringify(vm.test.a),
  () => console.log('> test.a changed')
);
vm.$watch(
  () => JSON.stringify(vm.test.b === void 0 ? {} : vm.test.b),
  () => console.log('> test.b changed')
);

setTimeout(() => {
  console.log('creating: test.b')
  Vue.set(vm.test, 'b', {})
}, 10)

setTimeout(() => {
  console.log('changing: test.b')
  vm.test.b = 1
}, 20)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>