在改变事件时,Vuejs会获得旧值

时间:2017-02-13 06:24:48

标签: javascript jquery vuejs2 vue.js

请参阅下面的我的代码段。如何获得已更改模型的旧值,在这种情况下是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>
&#13;
&#13;
&#13;

我正在尝试使用手表,但我无法找到任何帮助来观察一系列物品的年龄。

7 个答案:

答案 0 :(得分:8)

你不会像解释here那样得到元素变化的旧价值。此外,在观察对象时,在对象引用发生更改之前,您无法按照here所述获得较旧的值。

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

&#13;
&#13;
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))
    }
  }
});
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:6)

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

删除v-model并将其替换为手动处理。

重要的是要注意"although a bit magical, v-model is essentially syntax sugar for updating data on user input events (...)"。所以没有太大的伤害你可以删除它并直接处理事件,就像你几乎已经做的那样。

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

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

然后,为了实际更新该值,请将item.age = event.target.value添加到changeAge,如下所示:

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

注意:您可能希望使用@input,这是v-model实际使用的内容。

就是这样,它应该可以解决问题。如果您需要阻止更改,则可以省略分配,但是,您需要重置输入值。 item.age = item.age的{​​{1}}可以解决问题,但我不太确定会这样做。

注意:Vue.set(item, 'age', item.age)是一个字符串,如果您需要数字,请使用event.target.value

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

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

我没有准备好所有细节,所以我只是草稿:在parseInt(),而不是普通v-for,你放置另一个组件,比如{ {1}}。你把<input>放在上面。在组件内部,您可以创建<my-item>并转发v-model=item道具,并将其转发到<input> / value之外。在您的组件中,单个项目是一个道具,因此您可以直接将观察者附加到它。相关文档:Component BasicsCustomizing Component v-modelProps

答案 2 :(得分:3)

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

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

答案 3 :(得分:2)

道具替换 v模型 v模型是双向绑定,它将使您的状态变得复杂 然后在更改事件中手动修改年龄属性

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

答案 4 :(得分:2)

您可以简单地使用

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

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

在vue方法对象中

答案 5 :(得分:1)

https://vuejs.org/v2/api/#Vue-nextTick

 changeAge() {
             this.$nextTick(() => {
                // here the current values are set, do desired actions
                
            })
}

答案 6 :(得分:0)

我遇到了同样的问题。我通过将输入包装在 Vue 组件中并观察包装器组件中的属性来解决它。在观察者中,我调用了 $emit,将新值、旧值和项目作为参数传递。

<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>
                <item-age-input
                    :item="item"
                    @age-changed="ageChanged"></item-age-input>
            </td>
        </tr>
    </tbody>
</table>

<script>
Vue.component('item-age-input', {
    props: {
        item: {
            type: Object,
            required: true
        }
    },
    template: `<input type="text" name="qty" v-model="item.age">`,
    watch: {
        "item.age": function(newAge, oldAge) {
            this.$emit('age-changed', newAge, oldAge, this.item);
        }
    }
});

var app = new Vue({
    el:"#table1",
    data:{
        items:[{name:'long name One',age:21},{name:'long name Two',age:22}]
    },
    methods: {
        ageChanged: function(newAge, oldAge, item){
            alert(newAge + ', ' + oldAge);
            console.log(item);
        }
    }
});
</script>