【问题标题】:vue js watch multiple properties with single handlervue js 使用单个处理程序监视多个属性
【发布时间】:2017-08-01 21:34:41
【问题描述】:

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

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

【问题讨论】:

  • 取决于您的数据的结构。如果您将观察到的数据放在一个对象中,您可以使用 deep: true 属性观察单个对象,并触发该方法。您也可以观察整个数据对象,但我不建议这样做。
  • 我认为没有像here 讨论的那样有某种方法,您可以像完成here 那样创建计算属性,但这也不是很干净。

标签: vue.js vue-loader


【解决方案1】:

更新: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 的原始答案

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

    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('|');

【讨论】:

  • 截至您 4 月的更新,我对使用这种方法很感兴趣,但我无法找到文档,因为我无法获得正确的语法,只找到了 v2v3,但这些都没有显示我需要的语法。需要以下语法:export default { watch:{ --watcher for multiple props here-- } }
  • 使用 vue 2 和 composition-api 插件,它与一个返回值数组的函数一起工作:watch(() => [a, b], ....)
  • 使用 vue 2,当我控制台我在 watch 方法中获得的任何属性时,我得到 [Object object]。我猜它不起作用?
  • @aasutossh 答案将其强制转换为字符串。如果您需要任何其他类型,最好从计算属性返回一个对象。 startAndEnd() { const {start, end} = this; return { start, end }; },。然后,您可以在其 corect 类型中使用不同的值,例如 newVal.start 和 newVal.end。你必须确保每次都发出一个新创建的对象,这样你就不会在你的 oldVal 中得到变异的对象。
  • 我使用的是 3.0。我有一长串想要查看的变量,但我不关心它们的值。如何编写监视语句而不包含变量值?我没有任何运气想出语法,而且似乎没有任何关于此的文档。
【解决方案2】:

另一种可能性:

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 docs for vm.$watch的更多信息。

【讨论】:

  • 这对我很有帮助,但应该注意的是,我正在查看一组对象,为此我需要添加 {deep: true} 官方 Vue JS 文档实际上对这个主题很有帮助:vuejs.org/v2/api/#vm-watch
  • @JohnMellor 好的,很高兴知道。我在上面的示例中添加了链接和deep: true,以防万一
  • 这个太酷了,谢谢分享!!
【解决方案3】:

像这样:

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
  }
}

【讨论】:

  • 您可以简单地返回要跟踪的项目数组。 changeData() { return [this.propa, this.propb] }
  • 这是最好的答案。保留类型并且在没有 this.$watch 的情况下很容易实现。数组也可以,但是通过返回一个对象,您可以保持每个属性的名称不变,而不必依赖索引。
  • 这应该被标记为vue2的正确答案。
【解决方案4】:

首先,您的定义可以简化。 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")

【讨论】:

    【解决方案5】:

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

      @Watch('varA')
      @Watch('varB')
      private oneOfAboveChanged(newVal) {
        console.log(newVal)
      }
    

    【讨论】:

      【解决方案6】:

      我对 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
          }, {}),
        }
      }
      

      【讨论】:

        【解决方案7】:

        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>
        

        【讨论】:

          【解决方案8】:

          老问题,但答案可能对仍在使用 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])
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-23
            • 2016-04-07
            • 2017-07-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多