简体   繁体   中英

Vue computed property overwriting global state without vuex

I have a list of people who have scores. In state I have them listed in an array, one of the items in the array is 'scoreHistory' which is an array of objects containing their scores at different points in time. I want to filter this set for different time periods ie -5 days, -30 days so instead of just seeing the overall score I can see the scores if everyone started at 0 say 30 days ago.

I have it (kind of) working. See my code below:

filteredScores () {
  if(!this.people) {
    return
  }
  // Here I was trying to ensure there was a copy of the array created in order to not change the original array. I thought that might have been the problem.
  let allPeople = this.people.slice(0) // this.people comes from another computed property with a simple getter. Returns an array.

  let timeWindow = 30 //days
  const windowStart = moment().subtract(timeWindow,'days').toDate()

  for (const p of allPeople ) {
    let filteredScores = inf.scoreHistory.filter(score => moment(score.date.toDate()).isSameOrAfter(windowStart,'day'))

    p.scoreHistory=filteredScores
    //calculate new score
    p.score = inf.scoreHistory.reduce(function(sum,item) {
        return sum + item.voteScore
      },0)
  }
  return allInf
}

I expected it to return to me a new array where each person's score is summed up over the designated time period. It seems to do that OK. The problem is that it is altering the state that this.people reads from which is the overall data set. So once it filters all that data is gone. I don't know how I am altering global state without using vuex??

Any help is greatly appreciated.

Your problem isn't that you're modifying the array, but that you're modifying the objects within the array. You change the scoreHistory and score property of each item in the array. What you want to do instead is create a new array (I recommend using map ) where each item is a copy of the existing item plus a new score property.

filteredScores () {
  if(!this.people) {
    return
  }

  let timeWindow = 30 //days
  const windowStart = moment().subtract(timeWindow,'days').toDate()

  return this.people.map(p => {
    let filteredScores = p.scoreHistory.filter(score => moment(score.date.toDate()).isSameOrAfter(windowStart,'day'))

    //calculate new score
    let score = filteredScores.reduce(function(sum, item) {
      return sum + item.voteScore
    }, 0)

    // Create a new object containing all the properties of p and adding score
    return {
      ...p,
      score
    }
  }
})

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