javascript - Vue.js 使用 v-if 语句对列表进行小计

标签 javascript vue.js vuejs2

我想知道如何计算 vue.js 列表的总数。 我的情况有点复杂,所以请允许我举个例子。 假设我正在渲染一张发票项目表。这是我的代码:

<table>
<template v-for="(invoice_item, index) in invoice_items" v-if="invoice_item.category === 'widgets'">
    <tr>
        <td>@{{ invoice_item.name }}</td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.rate"></td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.quantity"></td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.activation_fee"></td>
        <td class="subtotal">@{{ computeSubTotal(invoice_item) }}</td>
    </tr>
</template>
</table>

对于每一行,我都计算了一个小计并将其显示在最后一列中。这是我的 vue.js javascript 中的代码:

computeSubTotal: function(invoice_item) {
    return(this.formatPrice((parseFloat(invoice_item.rate) * parseFloat(invoice_item.quantity) + parseFloat(invoice_item.activation_fee))));
},

这很好用。但是,现在我想显示所有小计的总和。换句话说:

enter image description here

我该如何实现?

谢谢!

最佳答案

使用计算属性进行计算。

console.clear()

new Vue({
  el: "#app",
  data: {
    invoice_items: [
      {
        name: "Community / Support",
        rate: 5.20,
        quantity: 1,
        activation_fee: 3.00,
        category: "widgets"
      },
      {
        name: "Infrastructure",
        rate: 269.00,
        quantity: 3,
        activation_fee: 1.00,
        category: "widgets"
      },
      {
        name: "Infrastructure",
        rate: 269.00,
        quantity: 3,
        activation_fee: 1.00,
        category: "stuff"
      },
    ]
  },
  computed: {
    // probably need a better name for this, but its just an example
    itemsWithSubTotal() {
      return this.invoice_items.map(item => ({
          item,
          subtotal: this.computeSubTotal(item)
      }))
    },
    // calculate the total of all the subtotalItems grouped by category
    totalByCategory() {
      // group the items by category
      let grouped = this.itemsWithSubTotal
        .reduce((acc, val) => {
          // This line does everything the lines below do, but in a very
          // terse, possibly confusing way.
          //(acc[val.item.category] = acc[val.item.category] || []).push(val)
          
          //if there is not already an array set up for the current
          //category, add one
          if (!acc[val.item.category]) 
            acc[val.item.category] = []
          // push the current value into the collection of values
          // for this category
          acc[val.item.category].push(val)
          // return the accumulator (object)
          return acc
        }, {})
        
      // create an object that has the total for each category
      return Object.keys(grouped).reduce((acc, val) => {
        acc[val] = grouped[val].reduce((total, item) => total += item.subtotal, 0)
        return acc
      }, {})
    }
  },
  methods: {
    computeSubTotal: function(invoice_item) {
      //formatPrice is removed here because its not defined in the question
      return ((parseFloat(invoice_item.rate) * parseFloat(invoice_item.quantity) + parseFloat(invoice_item.activation_fee)));
    },
  }
})
input {
  width: 5em
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <table>
    <template v-for="(invoice_item, index) in itemsWithSubTotal" v-if="invoice_item.item.category === 'widgets'">
    <tr>
        <td>{{ invoice_item.name }}</td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.item.rate"></td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.item.quantity"></td>
        <td><input type="number" class="inline-edit" v-model="invoice_item.item.activation_fee"></td>
        <td class="subtotal">{{ invoice_item.subtotal }}</td>
    </tr>
</template>
  </table>
  Total: {{totalByCategory["widgets"]}}
</div>

itemsWithSubTotal 可能看起来有点奇怪。

itemsWithSubTotal() {
  return this.invoice_items.map(item => ({
      item,
      subtotal: this.computeSubTotal(item)
  }))
},

基本上这会返回一个具有一个属性的新对象,item 指向原始项目和一个小计属性。我这样做是为了让 v-model 可以在模板中工作并自动更新计算属性。

关于javascript - Vue.js 使用 v-if 语句对列表进行小计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48433537/

相关文章:

javascript - 将 "more results..."文本添加到 ui bootstrap typeahead

Javascript 将函数作为对象传递会影响范围

vue.js - Nuxt 项目中没有布局文件夹

vuejs2 - Vuex 过滤状态

Javascript - 等待在错误的时间触发

javascript - Marionette:您可以为触发器和事件使用相同的事件配置吗?

javascript - 如何在BootstrapVue的Carousel组件中自定义控件和指示器?

javascript - 如何使用 vue.js 获取所选选项的索引

javascript - VueJS 调用简单方法不起作用后更新 Dom

vue.js - Vue2 : v-model does not support dynamic input types