7
votes

This question may also be applicable to Vue in general, but I am using Vuex for my project.

I have an array of objects in my store for which I would like to have a calculated property.

To simplify, assume my store is as follows:

const state = {
    numbers = [
        {num: 2, multiplier: 3},
        {num: 5, multiplier: 10},
        {num: 1, multiplier: 6}
    ]
};

Now, I want a calculated property on each object of the numbers array, such that the result is num * multiplier (eg. 2*3 = 6, 5*10 = 50)

One solution is to make a calculated property that returns the numbers array, plus the calculated field... eg:

const getterrs = {
    num_list(state){
        const list = state.numbers
        list.map(n=>{
            n.value=n.num*n.multiplier;
        );
        return list;
    }
}

That works, but it has a couple issues:

  • The array returned cannot be bound with v-model on the non-computed fields

  • The entire array will be recalculated whenever any element in the array is changed... I only want to recalculate the individual element that changed.

Is that possible with Vue/Vuex?

1
Have you ever found the solution? - user0103
Do you change the array through a mutation? I think doing this how you imagined it originally would not be worth it for the time and complexity of it. But the easiest way for this would be when you set this data, you also make another array in the state with just the calculated values, and in the mutation or wherever you set the data you could add the number/multiplier pair and calcualted value to both arrays, that would make result in kind of what you want, with much less computation at the cost of some extra space. - Komi

1 Answers

0
votes

You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:

const getters = {
    num_list(state){
        return state.numbers;
    }
}

Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:

computed: {
        num_list() {
            return this.$store.getters.num_list
        }
    }

and display it in your template like this:

<p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>

If you want to have the multiplication calculated as well you can have another computed property:

multiplied() {
    return this.num_list[0].num*this.num_list[0].multiplier
}

and echo it in the template with {{multiplied}}.

Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:

multipliedMethod(index) {
    return this.num_list[index].num*this.num_list[index].multiplier
}

Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:

<div v-for="(num, index) in num_list" :key="index">
  <p>{{num.num*num.multiplier}}</p>
</div>