Vue 3如何更新所有小计的总和

Vue 3 How update sum of all subtotals on change

我有一个应用程序,它从表单收集数据,然后将新的计数器对象推送到数组(计数器),然后呈现一个计数器组件,该组件可以递增和递减以更新该计数器的小计 属性。

我正在努力解决如何在所有小计发生变化时呈现它们的总计。我尝试使用计算 属性 但它只呈现最后添加的计数器的小计。

这是我的 AddCounters 组件

<template>
  ... form
    <div class="total-price-wrapper">
      <p class="total-text">Total Price {{ getTotals }}</p>
    </div>
  </div>
  <div class="counters-wrapper">
    <ul class="counters-list">
      <li
        class="counter-item"
        v-for="(counter, index) in counters"
        :key="index"
      >
        <Counter :counter="counter" />
      </li>
    </ul>
  </div>
</template>

<script>
import Counter from "./Counter.vue";
export default {
  data() {
    return {
      counters: [],
      grandTotal: 0,
      price: "",
      type: "",
      location: "",
      quantity: 0,
      counterId: 0,
      subtotal: null,
    };
  },
  components: {
    Counter,
  },
  methods: {
    addCounter() {
      let newCounter = {
        id: this.counterId + 1,
        type: this.type,
        location: this.location || "In & Out",
        price: this.price,
        quantity: this.quantity,
        subtotal: this.subtotal,
      };

      if (this.price !== "" && this.type !== "") {
        this.counters.push(newCounter);
      }

      this.price = "";
      this.type = "";
      this.location = "";
      this.quantity = 0;
      this.subtotal = null;

      this.counterId = newCounter.id;
    },
  },
  computed: {
    //This only works on last counter rendered
    getTotals: function () {
      const grandTotals = this.counters
        .map((counter) => {
          console.log("Subtotals", counter.subtotal);
          return counter.subtotal;
        })
        .reduce((prev, curr) => (prev = curr), 0);
      return grandTotals;
    },
  },
};
</script>

这是我的计数器组件的样子。

<template>
  ... UI methods below are wired up
    <div class="counter-subtotal-wraper">
      <label class="counter-subtotal-label">Subtotal</label>
      <span id="" class="counter-subtotal-display">{{ counter.subtotal }}</span>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    counter: Object,
  },
  methods: {
    deleteCounter() {
      console.log("Delete Counter Called");
    },
    incrementQty(counter) {
      counter.quantity += 1;
      this.getSubtotal(counter);
    },
    decrementQty(counter) {
      if (counter.quantity > 0) {
        counter.quantity -= 1;
        this.getSubtotal(counter);
      } else {
        counter.quantity = 0;
      }
    },
    getSubtotal: function (counter) {
      let count = counter.quantity;
      let price = counter.price;
      let subTotal = count * price;
      counter.subtotal = subTotal.toFixed(2);
    },
  },
};
</script>
getTotals: function () {
      const grandTotals = this.counters
        .map((counter) => {
          console.log("Subtotals", counter.subtotal);
          return counter.subtotal;
        })
        .reduce((prev, curr) => (prev = curr), 0);
      return grandTotals;
    },

在上面的 reduce 中,您将 prev 设置为等于当前值。换句话说,您每次都在覆盖该值,而不是进行加法。

相反,您应该添加到 prev:

getTotals: function () {
      const grandTotals = this.counters
        .map((counter) => {
          console.log("Subtotals", counter.subtotal);
          return counter.subtotal;
        })
        .reduce((prev, curr) => prev += curr, 0);
      return grandTotals;
    },

您也可以像这样压缩 mapreduce

getTotals: function () {
      const grandTotals = this.counters
        .reduce((prev, counter) => prev += counter.subtotal, 0);
      return grandTotals;
    },

编辑

counter.subtotal是一个字符串,所以在做加法之前需要转换成一个数字。

getTotals: function () {
      const grandTotals = this.counters
        .reduce((prev, counter) => prev += Number(counter.subtotal), 0);
      return grandTotals;
    },