Javascript Vuejs 在更改事件时获得旧值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42197822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:58:57  来源:igfitidea点击:

Vuejs get old value when on change event

javascriptjqueryvuejs2vue.js

提问by madi

Please refer to my snippet below. How can I get the old value of the changed model, in this case is the age in vuejs?

请参考我下面的片段。如何获取更改后模型的旧值,在这种情况下是 vuejs 中的年龄?

var app = new Vue({
  el:"#table1",
  data:{
   items:[{name:'long name One',age:21},{name:'long name Two',age:22}]
  },
  methods:{
    changeAge:function(item,event){
      alert(item.age);
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<table class="table table-cart" id="table1">
   <thead>
     <tr>
       <th>Name</th>
       <th>Age</th>
     </tr>
  </thead>
   <tbody>
     <tr v-for="(item,index) in items">
       <td>{{item.name}} :</td>       
       <td>
         <input type="text" name="qty"
                v-model="item.age"   
                @change="changeAge(item,$event)">
       </td>
     </tr>
   </tbody>
 </table>

I am trying to use watch, but I am not able to find any help in watching the age an array of items.

我正在尝试使用手表,但我无法在观看一系列项目的年龄方面找到任何帮助。

回答by Frax

This solution assumes that you need the old value only when handling the change coming from user input, and not a generic model change - which is probably the case. Below I added a sketch of solution watching all changes in if it's necessary, though perhaps it's better to control the other changes at the places they occur, and not in this component.

此解决方案假定您仅在处理来自用户输入的更改时才需要旧值,而不是通用模型更改 - 这可能是这种情况。下面我添加了一个解决方案草图,如果有必要,可以观察所有变化,尽管也许最好在它们发生的地方控制其他变化,而不是在这个组件中。

Drop v-modeland replace it with manual handling.

丢弃v-model并替换为手动处理。

It is important to note that "although a bit magical, v-model is essentially syntax sugar for updating data on user input events (...)". So without much harm you can remove it and handle the events directly, as you already almost do.

重要的是要注意“虽然有点神奇,但 v-model 本质上是用于更新用户输入事件数据的语法糖 (...)”。因此,您可以删除它并直接处理事件,而不会造成太大伤害,就像您几乎已经做到的那样。

First, replace v-modelwith :value. The input will still follow the item.ageupdates, but will not update the age automatically.

首先,替换v-model:value. 输入仍会跟随item.age更新,但不会自动更新年龄。

<input type="text" name="qty"
       :value="item.age"
       @change="changeAge(item,$event)">

Then, in order to actually update the value, add item.age = event.target.valueto changeAge, like this:

然后,为了实际更新值,添加item.age = event.target.valuechangeAge,如下所示:

changeAge: function(item, event){
  alert(item.age);  // Old value
  alert(event.target.value);  // New value
  item.age = event.target.value;  // Actual assignment
}

Note: you may want to use @input instead, that's what v-model actually uses.

注意:您可能想改用 @input,这就是 v-model 实际使用的。

And that's it, it should do the trick. If you need to prevent the change, you can just omit the assignment, however, you need to reset the input value. item.age = item.ageof Vue.set(item, 'age', item.age)may do the trick, but I'm not quite sure it will.

就是这样,它应该可以解决问题。如果您需要阻止更改,您可以省略赋值,但是,您需要重置输入值。item.age = item.ageofVue.set(item, 'age', item.age)可能会起作用,但我不太确定它会不会。

Note: event.target.valueis a string, if you need a number, use parseInt().

注意:event.target.value是一个字符串,如果需要数字,请使用parseInt().

Create a separate component instance for every item and create a watch there

为每个项目创建一个单独的组件实例并在那里创建一个手表

In case you need to watch all the changes. However, if you need that, perhaps you should do that in some other place, not this component.

如果您需要查看所有更改。但是,如果您需要这样做,也许您应该在其他地方而不是此组件中执行此操作。

I don't have all the details ready, so I'll just the general draft: in your v-for, instead of plain <input>, you place another component, say <my-item>. You put v-model=itemon it. Inside the component, you create the <input>and forward the valueprop to it, as well as forward it's input/changeevents outside. In your component single item is a single prop, so you can attach a watcher directly to it. Relevant docs: Component Basics, Customizing Component v-model, Props.

我还没有准备好所有的细节,所以我只是一般的草稿:在你的v-for,而不是普通的<input>,你放置另一个组件,比如<my-item>。你穿上v-model=item它。在组件内部,您创建<input>并将valueprop转发给它,以及将它的input/change事件转发到外面。在你的组件中,单个项目是一个单一的道具,所以你可以直接将一个观察者附加到它上面。相关文档:组件基础自定义组件v-model道具

回答by Saurabh

You dont get old value of element on-change as explained here. Also when watching an object, you can not get older value as explained hereuntil the reference of object changes.

为解释你并没有在变化元件的旧价值在这里。此外,在观察对象时,在对象的引用发生变化之前,您无法获得此处所述的较旧值。

To work around these you can create a computed property which will be clone of your itemsdata, and you can put a watcher over this computed property to get to know the old value as well, See working code below:

要解决这些问题,您可以创建一个计算属性,它将克隆您的items数据,并且您可以在此计算属性上放置一个观察者以了解旧值,请参阅下面的工作代码:

var app = new Vue({
  el:"#table1",
  data:{
   items:[{name:'long name One',age:21},{name:'long name Two',age:22}]
  },
  watch:{
    clonedItems: function(newVal, oldVal){
      alert(JSON.stringify(newVal));
      alert(JSON.stringify(oldVal));
    }
  },
  computed:{
    clonedItems: function(){
       return JSON.parse(JSON.stringify(this.items))
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<table class="table table-cart" id="table1">
   <thead>
     <tr>
       <th>Name</th>
       <th>Age</th>
     </tr>
  </thead>
   <tbody>
     <tr v-for="(item,index) in items">
       <td>{{item.name}} :</td>       
       <td>
         <input type="text" name="qty"
                v-model="item.age">
       </td>
     </tr>
   </tbody>
 </table>

回答by G...... T......

It may be too late. This worked for me as long as the function name inside the watch object is named as the variable which is watched. It only watches the specific variable.

可能为时已晚。只要监视对象内的函数名称被命名为被监视的变量,这对我有用。它只监视特定的变量。

watch:{
   items: function(newVal, oldVal){
      console.log("New value: "+ newVal + ", Old value: " + oldVal);
   },
   other_variable: function(newVal, oldVal){
      console.log("New value: "+ newVal + ", Old value: " + oldVal);
   }
}

回答by lynnic

replace v-modelwith valueprop v-model is two-way binding, it will make your state complex then manually modify age property in change event

valueprop替换v-modelv-model 是双向绑定,它会让你的状态变得复杂,然后在 change 事件中手动修改 age 属性

<input type="text" name="qty"
                :value="item.age"   
                @change="changeAge">



export default {
  change(val) {
     let ov = this.item.age
     let nv = val
     // do something
     // this.item.age = nv
   }
}

回答by Rahul Reghunath

You can simply use

你可以简单地使用

<input type="text" name="qty" v-model="item.age" @change="changeAge($event)">

and

changeAge: function(event){
  item = event.target.value;  // Actual assignment
}

in vue method object

在 vue 方法对象中