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

Vue父表格点击行时子表格重复显示问题排查与解决请求

问题分析与解决方案

嘿,我发现你遇到的子表格重复显示问题根源啦!你在HTML模板里做了重复的嵌套循环,导致同一组地区数据被多次渲染。

具体问题点

看你这段代码:

<template v-for="(xy, indexStop) in DistrictGDP" v-if="opened.includes(row.Id) && row.Id==xy.Id">
  <!-- 子表格表头 -->
  <template v-for="xy in DistrictGDP" v-if="opened.includes(row.Id) && row.Id==xy.Id">
    <!-- 地区数据行 -->
  </template>
</template>

这里外层已经通过v-for遍历了所有和当前邦匹配的地区,然后内层又再次遍历整个DistrictGDP数组并筛选相同条件的地区。举个例子:Rajasthan有2个地区,外层循环会执行2次,每次内层又会循环2次,最终就会渲染出4行重复的地区数据(2×2),这就是重复的核心原因。而且表头也会跟着外层循环重复出现,这也是额外的问题。

修复方案

我们需要简化结构,去掉重复的循环,同时确保表头只渲染一次。下面是修改后的完整代码:

修改后的HTML部分

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="table">
    <table class="table-fill">
      <thead>
        <tr>
          <th class="text-center">State/UT</th>
          <th class="text-center">1999-00</th>
          <th class="text-center">2000-01</th>
        </tr>
      </thead>
      <template v-for="row in stateGDP">
        <tr @click="toggle(row.Id)" :class="{ opened: opened.includes(row.Id) }">
          <td>{{ row.State }}</td>
          <td>{{ row['1999-00'] }}</td>
          <td>{{ row['2000-01'] }}</td>
        </tr>
        <!-- 仅当当前邦展开时显示子表格 -->
        <template v-if="opened.includes(row.Id)">
          <!-- 子表格表头:只渲染一次 -->
          <thead>
            <tr>
              <th class="text-center">District</th>
              <th class="text-center">1999-00</th>
              <th class="text-center">2000-01</th>
            </tr>
          </thead>
          <!-- 筛选并遍历当前邦对应的地区数据 -->
          <tr v-for="district in DistrictGDP.filter(d => d.Id === row.Id)" :key="district.District">
            <td>{{district.District}}</td>
            <td>{{district['1999-00']}}</td>
            <td>{{district['2000-01']}}</td>
          </tr>
        </template>
      </template>
    </table>
  </div>
</div>

关键修改说明

  1. 移除重复循环:去掉了外层多余的v-for="(xy, indexStop) in DistrictGDP",直接用v-if="opened.includes(row.Id)"判断是否展开子表格。
  2. 表头只渲染一次:把子表格表头放在展开判断的模板里,确保每个邦展开时只显示一个表头。
  3. 单次筛选数据:用DistrictGDP.filter(d => d.Id === row.Id)一次性筛选出当前邦的所有地区,再遍历这些结果,每个地区只会渲染一次。
  4. 添加key属性:给子表格的行加上:key="district.District",符合Vue列表渲染的最佳实践,避免控制台警告。

进阶优化(可选)

如果你的数据量比较大,每次渲染都用filter会有点性能开销,你可以在Vue的computed属性里预先把地区数据按邦的Id分组:

修改后的Vue代码

var app = new Vue({
  el: "#app",
  data(){
    return {
      opened:[],
      stateGDP: [
        { State: "Rajasthan", "1999-00": "2547", "2000-01": "3679",Id:"23" },
        { State: "Orissa", "1999-00": "38714", "2000-01": "38814",Id:"24" }
      ],
      DistrictGDP: [
        { State: "Rajasthan", District: "Jaipur", "1999-00": "2547", "2000-01": "3679", Id:"23" },
        { State: "Rajasthan", District: "Jodhpur", "1999-00": "2557", "2000-01": "3639", Id:"23" },
        { State: "Orissa", District: "Bhubaneswar", "1999-00": "1983", "2000-01": "2068", Id:"24" },
        { State: "Orissa", District: "Puri", "1999-00": "1923", "2000-01": "2008", Id:"24" }
      ]
    }
  },
  computed: {
    groupedDistricts() {
      // 按Id分组地区数据
      return this.DistrictGDP.reduce((acc, district) => {
        if (!acc[district.Id]) {
          acc[district.Id] = [];
        }
        acc[district.Id].push(district);
        return acc;
      }, {});
    }
  },
  methods:{
    toggle:function(Id) {
      const index = this.opened.indexOf(Id);
      if (index > -1) {
        this.opened.splice(index, 1)
      } else {
        this.opened.push(Id)
      }
    }
  }
})

然后HTML里的遍历部分改成:

<tr v-for="district in groupedDistricts[row.Id]" :key="district.District">

这样分组只会在数据变化时重新计算,渲染时直接取分组好的数据,性能会更好。

内容的提问来源于stack exchange,提问作者Lakshay Khandelwal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 22:17:58