Nested loops in table with template element gives

2019-08-29 03:54发布

问题:

I have a 4 way nested loop: Years > months > types > consultants.

I get this error:

RangeError: Maximum call stack size exceeded

I tried with only the keys (short version) to make a minimal as possible working thing so what you now see is without the values from the nested loops.

  • 4 way nested loop in table: Error
  • 3 way nested loop in table: Works
  • 4 way nested loop in unordered list: Works

Is there a restriction that you can not use more then 3 times the template element in table?

My table (short version):

<table>
  <thead>
    <tr>
      <td>head</td>
    </tr>
  </thead>
  <tbody>
    <template v-for="(years, y) in stats">
      <tr :key="y">
        <td>{{ y }}</td>
      </tr>
      <template v-for="(months, m) in years">
        <tr v-if="m !== 'total'" :key="y + m">
          <td>{{ m }}</td>
        </tr>
        <template v-for="(types, t) in months">
          <tr v-if="t !== 'total'" :key="y + m + t">
            <td>{{ t }}</td>
          </tr>
          <template v-for="(consultants, c) in types">
            <tr v-if="c !== 'total'" :key="y + m + t + c">
              <td>{{ c }}</td>
            </tr>
          </template>
        </template>
      </template>
    </template>
  </tbody>
</table>

My unordered list (short version):

<ul v-for="(years, y) in stats" :key="y">
  <li>
    {{ y }}
    <ul v-for="(months, m) in years" :key="y + m">
      <li v-if="m !== 'total'">
        {{ m }}
        <ul v-for="(types, t) in months" :key="y + m + t">
          <li v-if="t !== 'total'">
            {{ t }}
            <ul v-for="(consultants, c) in types" :key="y + m + t + c">
              <li v-if="c !== 'total'">{{ c }}</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

Creation of the nested loops:

const customer = await this.$http.get(`/api/customer/${customer_id}`)
this.stats = {}

customer.data.forEach(invoice => {
  const year = invoice.year
  const month = invoice.monthname
  const type = invoice.consultant_type
  const consultant = invoice.consultant

  const sales = invoice.sales
  const purchase = invoice.purchase
  const grossMargin = invoice.gross_margin

  // group by year
  if (year in this.stats) {
    this.stats[year].total.sales += sales
    this.stats[year].total.purchase += purchase
    this.stats[year].total.grossMargin += grossMargin
  } else {
    this.stats[year] = {
      total: {
        sales: sales,
        purchase: purchase,
        grossMargin: grossMargin,
      }
    }
  }

  // group by month
  if (month in this.stats[year]) {
    this.stats[year][month].total.sales += sales
    this.stats[year][month].total.purchase += purchase
    this.stats[year][month].total.grossMargin += grossMargin
  } else {
    this.stats[year][month] = {
      total: {
        sales: sales,
        purchase: purchase,
        grossMargin: grossMargin,
      }
    }
  }

  // group by type
  if (type in this.stats[year][month]) {
    this.stats[year][month][type].total.sales += sales
    this.stats[year][month][type].total.purchase += purchase
    this.stats[year][month][type].total.grossMargin += grossMargin
  } else {
    this.stats[year][month][type] = {
      total: {
        sales: sales,
        purchase: purchase,
        grossMargin: grossMargin,
      }
    }
  }

  // group by consultants
  if (consultant in this.stats[year][month]) {
    this.stats[year][month][type][consultant].sales += sales
    this.stats[year][month][type][consultant].purchase += purchase
    this.stats[year][month][type][consultant].grossMargin += grossMargin
  } else {
    this.stats[year][month][type][consultant] = {
      sales: sales,
      purchase: purchase,
      grossMargin: grossMargin,
    }
  }
})