71

目前我必须看一些属性。如果它们每个都发生变化,我必须调用相同的函数:

export default{
  // ...... rest of code 
  watch: {
    propa: function(after,before) {
      doSomething(after,before);
    },
    propb: function(after,before) {
      doSomething(after,before);
    }
    // ... so on
  }
}

所以我不得不在上面多次编写相同的代码。是否可以简单地监视所有属性并调用它们的更改处理程序,而不必多次编写相同的代码?

PS:我使用的是 vue 1.x

4

8 回答 8

100

更新:2020 年 4 月

对于使用 Vue 3 的人,watch API 可以接受多个来源

import { watch, ref } from 'vue';

export default {
  setup(() => {
    const a = ref(1), b = ref('hello');

    watch([a, b], ([newA, newB], [prevA, prevB]) => {
      // do whatever you want
    });
  });
};


Vue 2 的原始答案

没有官方方法可以解决您的问题(请参阅此)。但是您可以使用计算属性作为技巧:

    export default {
      // ...
      computed: {
        propertyAAndPropertyB() {
          return `${this.propertyA}|${this.propertyB}`;
        },
      },
      watch: {
        propertyAAndPropertyB(newVal, oldVal) {
          const [oldPropertyA, oldProvertyB] = oldVal.split('|');
          const [newPropertyA, newProvertyB] = newVal.split('|');
          // doSomething
        },
      },
    }

如果您只想做某事而不关心什么是新/旧值。忽略两行

    const [oldPropertyA, oldProvertyB] = oldVal.split('|');
    const [newPropertyA, newProvertyB] = newVal.split('|');
于 2017-08-24T05:08:54.840 回答
27

另一种可能:

new Vue({
  el: '#app',
  data: {
    name: 'Alice',
    surname: 'Smith',
    fullName: '' // IRL you would use a computed for this, I'm updating it using a watch just to demo how it'd be used
  },
  mounted() {
    this.$watch(vm => [vm.name, vm.surname], val => {
      
      this.fullName = this.name + ' ' + this.surname;
      
    }, {
      immediate: true, // run immediately
      deep: true // detects changes inside objects. not needed here, but maybe in other cases
    }) 
  }
});
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div>
    name:<input v-model="name">
  </div>
  <div>
    surname:<input v-model="surname">
  </div>
  <div>
    full name: {{ fullName }}
  </div>
</div>

有关Vue API 文档的vm.$watch更多信息。

于 2018-04-16T23:16:45.203 回答
24

像这样:

data() {
  return {
    propa: '',
    propb: ''
  }
},
computed: {
  changeData() {
    const { propa, propb } = this
    return {
      propa,
      propb
    }
  }
},
watch: {
  changeData: {
    handler: function(val) {
      console.log('value change: ', val)
    },
    deep: true
  }
}
于 2019-09-10T04:40:37.290 回答
6

首先,您的定义可以简化。doSomething似乎不是 Vue 上的一种方法,因此您的手表可能只是

watch:{
    propa: doSomething,
    propb: doSomething
}

其次,有时重要的是要记住 Vue 定义对象只是普通的 javascript 对象。它们可以被操纵。

如果您想查看数据对象中的每个属性,您可以执行以下操作

function doSomething(after, before){
  console.log(after,before);
}

function buildWatch(def){
  if (!def.watch)
    def.watch = {};
  for (let prop of Object.keys(def.data))
    def.watch[prop] = doSomething;
  return def;
}

let vueDefinition = {
  data:{
    propa: "testing",
    propb: "testing2",
    propc: "testing3"
  }
}

export default buildWatch(vueDefinition)

如果您只想查看一些已定义的属性列表:

// First argument is the definition, the rest are property names
function buildWatch(def){
  if (!def.watch)
    def.watch = {};
  const properties = Array.prototype.slice.call(arguments,1); 
  for (let prop of properties)
    def.watch[prop] = doSomething;
  return def;
}

export default buildWatch(vueDefinition, "propa", "propb")
于 2017-03-11T18:24:51.360 回答
4

我对 vue2 的解决方案:

export default {
  data() {
    return {
      status: null,
      name: null,
      date: null,
      mobile: null,
      page: 1,
    }
  },
  watch: {
    ...["status", "name", "date", "mobile", "page"].reduce((acc, currentKey) => {
      acc[currentKey] = (newValue) => {
        // doSomething
        // console.log(newValue, currentKey)
      }
      return acc
    }, {}),
  }
}
于 2021-06-03T08:29:15.647 回答
4

对于 Vue 打字稿,您可以这样做。经测试。

  @Watch('varA')
  @Watch('varB')
  private oneOfAboveChanged(newVal) {
    console.log(newVal)
  }
于 2020-09-23T14:34:24.453 回答
2

vm.$data

如果你想听里面的所有属性data(),你可以使用this.$data

<script>
export default {
  data () {
    return {
      propA: 'Hello',
      propB: 'world'
    }
  }
  watch: {
    $data (newValue) { // Watches for any changes in data()
      // Do something with the new data
    }    
  }
}
</script>
于 2021-07-03T11:13:17.363 回答
0

老问题,但答案仍然可能对仍在使用 vue 1 的人有用。

您可以通过将它们用引号括起来来观看多个道具:

data() {
   return {
      foo: {
         prop1: 1,
         prop2: 2,
      }
   }
}
watch: {
    '[foo.prop1, foo.prop2]'(newVal, oldVal) {
        //do sth
        console.log(newVal); // prints ([prop1, prop2])
        console.log(oldVal); // prints ([prop1, prop2])
    }
}
于 2021-09-09T08:32:10.977 回答