首页 > 解决方案 > 向购物车添加选项会增加所有计数器

问题描述

当我将一个选项添加到购物车时,所有选项的计数器同时增加。我尝试过使用 Vuex,但我对它缺乏经验,所以我采用了一种更简单的方法。如何在不增加所有计数器的情况下添加选项?

(我整理了一个代码示例,以便更容易解释。)

<template>
    <div>
         <div v-for="optionTests in ArrayOption" :key="optionTests.id">
            <p>{{ optionTests.id}}</p>
            <p>{{ optionTests.name}}</p>
            <p>{{ optionTests.description}}</p>
            <button  @click="testCount -= 1" :disabled="testCount < 1">-</button>
            <p>{{ testCount }}</p>
            <button @click="testCount += 1" :disabled="testCount > 0">+</button>
        </div>
    </div> 
</template>
 
<script>
import axios from 'axios'
 
export default {
    data(){
        return{
            ArrayOption:[
                {
                    id:1,
                    name: 'option1'
                    description: 'je suis l option 1 ajoute moi au panier'
                },
                {
                    id:2,
                    name: 'option2'
                    description: 'je suis l option 2 ajoute moi au panier'
                },
                {
                    id:3,
                    name: 'option3'
                    description: 'je suis l option 3 ajoute moi au panier'
                },
                {
                    id:4,
                    name: 'option4'
                    description: 'je suis l option 4 ajoute moi au panier'
                }
            ],
            testCount:0,
        }
    }
}

在此处输入图像描述

标签: javascriptvue.jsvue-reactivity

解决方案


这里发生的情况是,当您为数组中的每个选项渲染一张独特的卡片时,您的计数器都连接到data.

这意味着当您更改一个计数器时,所有计数器都会更新以显示新的总数,因为它们实际上都在表面下显示相同的数字,即使它们出现在不同的位置。

为了解决这个问题,您需要单独存储选项计数,以便可以单独读取和迭代它们。


这是您可以执行此操作的一种方法。

testCount您可以将每个选项计数器存储为计数器对象中的键,而不是直接显示和操作,以便每个选项计数器可以自己递增或递减:

testCounter: { 
  "option1": 0, 
  "option2": 0,
  "option3": 0,
  "option4": 0 
}

这是一个展示这一点的交互式示例!

请注意,我必须使用一个特殊的 Vue 实例方法,vm.$set()来使各个计数器反应。Vue 无法跟踪您何时在 object 中动态创建新属性,因此我们必须明确告诉 Vue 为我们添加新键,使用vm.$set([object], [key name], [initial value]).

new Vue({
  el: '#app',
  data() {
    return {
      arrayOption: [{
          id: 1,
          name: 'option1',
          description: 'je suis l option 1 ajoute moi au panier'
        },
        {
          id: 2,
          name: 'option2',
          description: 'je suis l option 2 ajoute moi au panier'
        },
        {
          id: 3,
          name: 'option3',
          description: 'je suis l option 3 ajoute moi au panier'
        },
        {
          id: 4,
          name: 'option4',
          description: 'je suis l option 4 ajoute moi au panier'
        }
      ],
      testCount: {},
    }
  },
  created() {
    // Important setup step–
    //  this.$set makes the counter properties reactive
    //  so that the DOM updates when you click a counter
    this.arrayOption.forEach(op => this.$set(this.testCount, op.name, 0));
  },
});
.card {
  background: #bbc0c4;
  border: solid;
  padding: 5px;
  margin: 5px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-content: space-around;
  justify-content: space-around;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <div>
    <p>Values: {{ testCount }}</p>
    <div v-for="optionTest in arrayOption" :key="optionTest.id" class="card">
      <p>{{ optionTest.id }}</p>
      <p>{{ optionTest.name }}</p>
      <p>{{ optionTest.description }}</p>
      <button @click="testCount[optionTest.name] -= 1" :disabled="testCount[optionTest.name] < 1">-</button>
      <p>{{ testCount[optionTest.name] }}</p>
      <button @click="testCount[optionTest.name] += 1" :disabled="testCount[optionTest.name] > 0">+</button>
    </div>
  </div>
</div>


推荐阅读