vue js 使用单个处理程序监视多个属性

Posted

技术标签:

【中文标题】vue js 使用单个处理程序监视多个属性【英文标题】:vue js watch multiple properties with single handler 【发布时间】: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 那样创建计算属性,但这也不是很干净。 【参考方案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 月的更新,我对使用这种方法很感兴趣,但我无法找到文档,因为我无法获得正确的语法,只找到了 v2 和v3,但这些都没有显示我需要的语法。需要以下语法: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])
    

【讨论】:

以上是关于vue js 使用单个处理程序监视多个属性的主要内容,如果未能解决你的问题,请参考以下文章

Vue 核心

Vue 核心

express.js - 单行中多个路由的单个路由处理程序

Vue基础(中):数据代理事件处理计算和监视属性class与style绑定

Vue.js watch监视属性

Node.js 产生多个进程