【问题标题】:Vuejs get old value when on change eventVuejs 在更改事件时获取旧值
【发布时间】:2017-07-01 01:41:40
【问题描述】:

请参考下面我的sn-p。如何获取更改模型的旧值,在这种情况下是 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>

我正在尝试使用手表,但在查看一系列项目的年龄时找不到任何帮助。

【问题讨论】:

  • 您的 changeAge(item,$event) 实际上帮助我解决了另一个问题。感谢分享。

标签: javascript jquery vuejs2 vue.js


【解决方案1】:

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

删除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.ageVue.set(item, 'age', item.age) 可能会成功,但我不太确定它会不会。

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

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

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

我还没有准备好所有的细节,所以我只写一个大致的草稿:在你的v-for 中,而不是普通的&lt;input&gt;,你放置另一个组件,比如&lt;my-item&gt;。你把v-model=item放在上面。在组件内部,您创建&lt;input&gt; 并将value 属性转发给它,并将它的input/change 事件转发到外部。在您的组件中,单个项目是单个道具,因此您可以直接将观察者附加到它。相关文档:Component BasicsCustomizing Component v-modelProps

【讨论】:

  • 如果使用输入[日期],如何从调用方法重置输入中显示的日期?
  • 你的意思是,type="date" 的输入?我认为他们在 Vue 中没有特别的支持,你必须在那里将值视为字符串?也许最好的选择是找到一些现成的日期选择器组件,它支持 v-model - 然后它与通常的文本输入大致相同。
【解决方案2】:

here 所述,您不会获得元素 on-change 的旧值。此外,在查看对象时,您无法获得较旧的值,如 here 所述,直到对象的引用发生更改。

要解决这些问题,您可以创建一个计算属性,该属性将克隆您的 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>

【讨论】:

  • 这意味着对于所有更改,此事件都将被触发。我只需要发生 item.age 更改事件。您的解决方案很好,但有没有办法使其具体化?就像我退格一样,事件也会被触发
  • @madi 一种选择是拥有一个计算属性,它返回年龄,并在其上设置观察者。
  • 东西在计算属性中,我们无法获取当前项目。所以这就是让人困惑的地方。不敢相信 Vue 有这么大的限制
  • return JSON.parse(JSON.stringify(this.items)); 更改为以下内容:let newItems = this.items.slice(0);return newItems; 为什么返回数组的副本,这不起作用?为什么你的有效?
  • @soarinblue 因为你没有复制,你只是将相同的引用分配给其他变量并返回该变量,所以你返回相同的引用,我在克隆它后返回一个新对象.您也可以使用提到的其他方式here
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    value 属性替换 v-model v-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
       }
    }
    

    【讨论】:

      【解决方案5】:

      你可以简单地使用

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

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

      在vue方法对象中

      【讨论】:

      • 旧值在哪里?
      • @Z.Khullah 您应该使用:value 而不是v-model 来获取旧值。然后使用 changeAge($event, qty) 方法改变值。
      • @Z.Khullah 旧值在qty,新值在event.target.value
      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        我遇到了同样的问题。我通过将输入包装在 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>
        

        【讨论】:

          猜你喜欢
          • 2012-02-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-15
          • 2019-01-30
          • 2019-07-08
          • 1970-01-01
          • 2021-06-22
          相关资源
          最近更新 更多