i have a very simple app that increment counter value for each array item individually. the problem is when i am incrementing the counter value, it updates for all array items
i know that it's possible to update counter value with each index of the array but can't find a better way to do it
<script setup>
const counter = ref(0)
const increment = () => {
counter.value = counter.value 1
}
const data = [{ name: 'john' }, { name: 'paul' }]
</script>
<template>
<div v-for="item in data" :key="item.name">
<div style="display: flex; gap:2rem">
<span>Name: {{ item.name }}</span>
<span>Age:{{ counter }}</span>
<button @click="increment">
increment
</button>
</div>
</div>
</template>
CodePudding user response:
Now you have only one counter. I understand that you want individual counter for each person.
Our people are:
1. { name: 'john' }
2. { name: 'paul' }
If we want to have individual counter, we need to add counter for individual person (with default state, so counter is equal to 0):
1. { name: 'john', counter: 0 }
2. { name: 'paul', counter: 0 }
Now we can remove our single counter and increment function:
const counter = ref(0)
const increment = () => {
counter.value = counter.value 1
}
Next, change displayed counter (to handle our new individual counter) from:
<span>Age:{{ counter }}</span>
to:
<span>Age:{{ item.counter }}</span>
And our click function should increment person's individual counter so:
<button @click="item.counter ">
increment
</button>
The last thing is wrapping our data variable in ref. The same you did with single counter. We have to share state between rerenders:
const data = ref([
{ name: 'john', counter: 0 },
{ name: 'paul', counter: 0 },
]);
At the end our code should look like this:
<script setup>
import { ref, computed } from 'vue';
const data = ref([
{ name: 'john', counter: 0 },
{ name: 'paul', counter: 0 },
]);
</script>
<template>
<div v-for="item in data" :key="item.name">
<div style="display: flex; gap: 2rem">
<span>Name: {{ item.name }}</span>
<span>Age:{{ item.counter }}</span>
<button @click="item.counter ">increment</button>
</div>
</div>
</template>
And there is a stackblitz: https://stackblitz.com/edit/vitejs-vite-xthp6v?file=src/components/HelloWorld.vue
CodePudding user response:
To achieve the requirement, you have to bind the counter
property in each object. So that you can play with it individualy.
Working Demo :
new Vue({
el: '#app',
data: {
data: [{ name: 'john', counter: 0 }, { name: 'paul', counter: 0 }],
},
methods: {
increment(index) {
this.data[index].counter = this.data[index].counter 1
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(item, index) in data" :key="index">
<div style="display: flex; gap:2rem">
<span>Name: {{ item.name }}</span>
<span>Age: {{ item.counter }}</span>
<button v-on:click="increment(index)">
increment
</button>
</div>
</div>
</div>