简体   繁体   中英

When I add .push function in my code for loop breaks

I had an array which has all orders with details(order-time, order-details, prices etc.), I want to find total prices for each month and get them all in an array.

  data(){
    checks:[//there is data from database]
    months:["2019-01","2019-02","2019-03","2019-04","2019-05","2019-06","2019-07","2019-08","2019-09","2019-10","2019-11","2019-12"],
    monthlyTotal:0,
    monthlyTotalsArr:[]
  },
  computed:{
   calcTotalMonthly(){
     for(let i=0; i<this.months.length; i++){
            this.checks.forEach((item => {
               if(item.orderTime.includes(this.months[i])){
                 item.bill.forEach(prod => {
                   this.monthlyTotal += parseInt(prod.price);
                 });
               }    
             }));
              this.monthlyTotalsArr.push(this.monthlyTotal);
             this.monthlyTotal = 0; 
         } return this.monthlyTotalsArr;

   }
  }

When I run this had an error [Vue warn]: You may have an infinite update loop in a component render function. , and monthlyTotalsArr.length will be like 1220.

If I delete this.monthlyTotalsArr.push(this.monthlyTotal); and console.log(this.monthlyTotal); i just saw 12 results as it's supposed to be, but I do not know why the push function breaks the loop.This is my problem, finally I want to see 12 different elements in monthlyTotalsArr .

A computed property should not have side effects. In this case you are modifying both monthlyTotal and monthlyTotalsArr . There's no need to do that, you can just use local variables inside the function and then return the computed value.

What's happening is that monthlyTotalArr is being registered as a dependency of this computed property. But you're then immediately changing it, which will mark the computed property as needing recalculating. It keeps going round in a loop trying to recalculate it but every time its dependencies change and it needs to go round again.

You should be able to write it something like this:

calcTotalMonthly () {
  return this.months.map(month => {
    let monthlyTotal = 0

    for (const check of this.checks) {
      if (check.orderTime.includes(month)) {
        for (const prod of check.bill) {
          monthlyTotal += parseInt(prod.price)
        }
      }    
    }

    return monthlyTotal
  })
}

I've swapped the forEach calls to for / of loops. That isn't required but I think it makes it easier to follow. The main loop I've swapped to use map as that seems to be what it's really doing.

You can rename calcTotalMonthly to monthlyTotalsArr if that's how you want to refer to that array elsewhere. The data properties monthlyTotal and monthlyTotalsArr are both removed in my version.

I haven't attempted to address the potential performance problem from having 3 nested loops.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM