Vue - 状态正在更新所有数组项

Vue - state is updating for all array items

我有一个非常简单的应用程序,它可以单独增加每个数组项的计数器值。问题是当我增加计数器值时,它会更新所有数组项

我知道可以用数组的每个索引更新计数器值,但找不到更好的方法

<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>

现在你只有一个计数器了。我了解到您希望每个人都有单独的计数器。

我们的员工是:

 1. { name: 'john' }
 2. { name: 'paul' }

如果我们想要有个人计数器,我们需要为个人添加计数器(默认状态,因此计数器等于0):

 1. { name: 'john', counter: 0 }
 2. { name: 'paul', counter: 0 }

现在我们可以删除我们的单个计数器和增量函数:

const counter = ref(0)
const increment = () => {
  counter.value = counter.value + 1
}

接下来,更改显示的计数器(以处理我们新的个人计数器):

<span>Age:{{ counter }}</span>

至:

<span>Age:{{ item.counter }}</span>

我们的点击函数应该增加个人计数器,所以:

<button @click="item.counter++">
  increment
</button>

最后一件事是将我们的数据变量包装在 ref 中。与您对单个计数器所做的相同。我们必须在重新渲染之间共享状态:

const data = ref([
  { name: 'john', counter: 0 },
  { name: 'paul', counter: 0 },
]);

最后我们的代码应该是这样的:

<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>

还有一个 stackblitz: https://stackblitz.com/edit/vitejs-vite-xthp6v?file=src%2Fcomponents%2FHelloWorld.vue

要达到要求,必须在每个对象中绑定counter 属性。这样你就可以个性化地玩了。

工作演示:

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>