VUE手表触发无限循环

时间:2018-02-27 18:03:00

标签: javascript vuejs2

我是使用VUE.Js的新手,我创建了一个非常简单的应用来试用它是如何工作的。

问题立即发生在我运行应用程序时,在无限循环中触发变量监视。我无法弄清楚为什么。有一个v-for循环但是在一个只有两个元素的数组上。

最初SubTotal应为0.但是一旦应用程序运行,它就会触发Buy方法,即使我没有点击“购买”按钮,子总数最终为442.37999999999965。

感谢您的帮助。

这是jsfiddle Beer shopping cart

HTML:

<div id = "growler">      
  <table>
    <tr>
      <th style='width:150px'>Beer</th>
      <th style='width:50px'>Price</th>
      <th style='width:30px'></th>
    </tr>

    <tr v-for = "beer in beers">
      <td>{{ beer.name }}</td>
      <td>{{ beer.price }}</td>
      <td>        
        <button :click="buy(beer)">buy</button>        
      </td>
    </tr>

    <tr>
      <td>SubTotal</td>
      <td>{{subTotal}}</td>
      <td></td>
    </tr>
  </table>
</div>

JS:

  new Vue({
  el: "#growler",
  data: {
      beers: [
        {name: 'Ahool Ale', price: 2.00}, 
        {name: 'Agogwe Ale', price: 2.38}        
      ],
      shoppingCart: [], 
      subTotal: 0.00        
  }, 
  watch: {
    shoppingCart: function() {
        console.log('shopping cart watch triggered');
      this.updateSubTotal();
    }
  }, 
  methods: {
    updateSubTotal: function () {
      var s=this.shoppingCart.length;
      var t=0;
      for (var i=0;i<s; i++){
        t += this.shoppingCart[i].price;
      }
      this.subTotal = t;
    }, 
    buy: function (beer) {
        console.log('beer pushed on array');
      this.shoppingCart.push(beer);
    }
  },   
  beforeCreate: function() {
    console.log('beforeCreate');
  },
  created: function() {
    console.log('created');                    
  },
  beforeMount: function() {
    console.log('beforeMount');                    
  },
  mounted: function() {
    console.log('mounted');                    
  },
  beforeUpdate: function() {
    console.log('beforeUpdate');
  },
  updated: function() {
    console.log('updated');
  },
  beforeDestroy: function() {
    console.log('beforeDestroy');
  },
  destroyed: function() {
    console.log('afterDestroy');
  }

});

1 个答案:

答案 0 :(得分:3)

我发现了你的错误:

<button :click="buy(beer)">buy</button>  

您在点击处理程序中使用了:v-bind)而不是@v-on:)。

首次绑定时,会调用该函数一次并更新shoppingCart。这将更新subTotal数据,这将强制重新呈现DOM,由于buy,这将再次触发:bind功能。

修正:

<button @click="buy(beer)">buy</button>  
<!-- or -->
<button v-on:click="buy(beer)">buy</button>  

您的代码的建议更改:

使用计算属性而不是方法来更新表示其他值之和的属性:

&#13;
&#13;
new Vue({
  el: "#growler",
  data: {
    beers: [{
        name: 'Ahool Ale',
        price: 2.00
      },
      {
        name: 'Agogwe Ale',
        price: 2.38
      }
    ],
    shoppingCart: []
  },
  watch: {
    shoppingCart: function() {
      console.log('shopping cart watch triggered');
    }
  },
  computed: {
    subTotal: function() {
      return this.shoppingCart.reduce(function(total, beer) {
        return total + beer.price;
      }, 0);
    }
    }
  },
  methods: {
    buy: function(beer) {
      this.shoppingCart.push(beer);
    }
  },

});
&#13;
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<div id="growler">
  <button>buy</button>
  <table>
    <tr>
      <th style='width:150px'>Beer</th>
      <th style='width:50px'>Price</th>
      <th style='width:30px'></th>
    </tr>

    <tr v-for="beer in beers">
      <td>{{ beer.name }}</td>
      <td>{{ beer.price }}</td>
      <td>
        <button @click="buy(beer)">buy</button>
      </td>
    </tr>

    <tr>
      <td>SubTotal</td>
      <td>{{subTotal}}</td>
      <td></td>
    </tr>
  </table>
</div>
&#13;
&#13;
&#13;