You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js:如何在v-for语句内计算值总和并动态更新小计

搞定Vue表格的小计与实时总计更新

嘿,我来帮你解决这个问题!看你的代码,你是想给表格每行做小计,还要在输入框变化时自动更新总计对吧?Vue的响应式系统其实能很优雅地处理这个,不用手动绑定keyup也能实时更新,下面给你两种方案:

一、计算每行小计(subtotal)

首先假设你的表格是按行循环的(比如每行对应一组configs),小计就是这一行所有输入框的score总和。

推荐方案:用计算属性自动响应变化

这种方式最符合Vue的设计,数据变了计算结果自动更新,不用手动写事件:

<template>
  <table>
    <!-- 假设你的行是从rows数组循环来的 -->
    <tr v-for="(row, idx) in rows" :key="idx">
      <td v-for="config in row.configs" v-if="config">
        <input 
          type="number" 
          v-model.number="config.score" 
          <!-- 这里不用绑keyup,v-model已经帮你监听数据变化啦 -->
        >
      </td>
      <!-- 直接调用方法计算当前行的小计 -->
      <td><span class="subtotal">{{ getRowSubtotal(row.configs) }}</span></td>
    </tr>
    <!-- 总计行 -->
    <tr>
      <td colspan="你需要的列数">
        <span class="total">{{ getOverallTotal() }}</span>
      </td>
    </tr>
  </table>
</template>

<script>
export default {
  data() {
    return {
      rows: [
        // 举个例子,你的数据大概是这样的
        { configs: [{ score: 0 }, { score: 0 }] },
        { configs: [{ score: 0 }, { score: 0 }] }
      ]
    };
  },
  methods: {
    getRowSubtotal(configs) {
      // 先过滤掉无效的config(对应你的v-if="config"),然后求和
      return configs
        .filter(c => c)
        .reduce((sum, config) => sum + (config.score || 0), 0);
    },
    getOverallTotal() {
      // 把所有行的小计加起来就是总计
      return this.rows.reduce((total, row) => {
        return total + this.getRowSubtotal(row.configs);
      }, 0);
    }
  }
};
</script>

备选方案:保留你的keyup事件

如果你一定要用keyup触发计算,那可以给每行加个subtotal字段存结果,然后在事件里更新:

<template>
  <table>
    <tr v-for="(row, idx) in rows" :key="idx">
      <td v-for="config in row.configs" v-if="config">
        <input 
          type="number" 
          v-model.number="config.score" 
          @keyup="updateScores(row)"
        >
      </td>
      <td><span class="subtotal">{{ row.subtotal }}</span></td>
    </tr>
    <tr>
      <td colspan="你需要的列数">
        <span class="total">{{ total }}</span>
      </td>
    </tr>
  </table>
</template>

<script>
export default {
  data() {
    return {
      rows: [
        { configs: [{ score: 0 }, { score: 0 }], subtotal: 0 },
        { configs: [{ score: 0 }, { score: 0 }], subtotal: 0 }
      ],
      total: 0
    };
  },
  methods: {
    updateScores(row) {
      // 计算当前行的小计
      row.subtotal = row.configs
        .filter(c => c)
        .reduce((sum, c) => sum + (c.score || 0), 0);
      // 同步更新总计
      this.calculateTotal();
    },
    calculateTotal() {
      this.total = this.rows.reduce((sum, row) => sum + row.subtotal, 0);
    },
    // 页面加载时先算一次初始值
    mounted() {
      this.rows.forEach(row => this.updateScores(row));
      this.calculateTotal();
    }
  }
};
</script>

几个重要的小细节

  • 一定要加v-model.number!不然输入的数字会变成字符串,求和的时候会变成拼接,结果全错
  • 记得过滤掉null/undefined的config,和你模板里的v-if="config"对应上
  • 计算属性的方案更省心,数据一变自动更,优先选这个哦

这样不管哪个输入框改值,小计和总计都会实时跟着变啦~

内容的提问来源于stack exchange,提问作者Famurewa Taiwo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:28:11