Vue 为列表中的每个项目保存 localStorage

Vue save localStorage for each items in list

我在一个项目中,我在数据中硬编码一个列表(一些 DC 漫画)。我在 Tailwind 中使用 Vue.js。在每本漫画下面有两个按钮(一个是我买的,另一个是我读的,有 2 个布尔值)。

我正在使用 localStorage 来保持进度,但问题是... 我可以在 buy = true and/or read = true 上设置一些漫画(或 false),但我的网站将 localstorage 的密钥保留在我修改的最后一项上。因此,无论我做什么,如果我在某个项目上设置 buy = true 或 false 和 read = false 或 false,然后刷新页面,所有项目都会进行相同的修改。所以我不能对每个项目单独做任何事情。

我的项目组件模板:

<template>
  <div class="rounded-lg mx-2 md:mx-8 mb-8">
    <div class="relative shadow-lg rounded-lg">
      <img class="h-56 w-64 md:h-56 md:w-64 object-cover rounded-t-lg" :src=cover alt="cover">
      <h3 class="relative z-50 -mt-10 text-xs text-center uppercase py-1 font-medium bg-black bg-opacity-50 text-white">
        {{ collection }}
      </h3>
      <h3 class="relative z-50 text-xs rounded-b-lg text-center uppercase py-1 font-medium bg-black text-white">
        {{ title }}
      </h3>
      <!-- overlay -->
      <div v-if="buy === true" class="absolute flex items-center justify-center bg-gray-800 bg-opacity-75 p-2 rounded-lg w-full h-full z-50 top-0 right-0 flex justify-end space-x-4">
        <div class="h-10 w-10 text-white bg-green-500 rounded-full flex items-center justify-center">
          <svg class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
            <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
            <circle cx="9" cy="19" r="2" />
            <circle cx="17" cy="19" r="2" />
            <path d="M3 3h2l2 12a3 3 0 0 0 3 2h7a3 3 0 0 0 3 -2l1 -7h-15.2" />
          </svg>
        </div>
        <div v-if="read === true" class="h-10 w-10 text-white bg-green-500 rounded-full flex items-center justify-center">
          <svg class="w-8 h-8" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
            <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
            <circle cx="12" cy="12" r="9" />
            <path d="M9 12l2 2l4 -4" />
          </svg>
        </div>
      </div>
    </div>
    <!-- buttons -->
    <div class="relative z-50 flex justify-end mt-2 space-x-6 mr-2">
      <button @click="toggleBuy" class="p-1 flex justify-center rounded-full text-gray-700 bg-gray-400 text-xs cursor-pointer uppercase font-medium focus:outline-none">
        <svg class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.7" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
          <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
          <circle cx="9" cy="19" r="2" />
          <circle cx="17" cy="19" r="2" />
          <path d="M3 3h2l2 12a3 3 0 0 0 3 2h7a3 3 0 0 0 3 -2l1 -7h-15.2" />
        </svg>
      </button>
      <button @click="toggleRead" class="p-1 flex justify-center rounded-full text-gray-700 bg-gray-400 text-xs cursor-pointer uppercase font-medium focus:outline-none">
        <svg class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
          <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
          <circle cx="12" cy="12" r="9" />
          <path d="M9 12l2 2l4 -4" />
        </svg>
      </button>
    </div>
  </div>
</template>

这是我的项目组件的JS代码

<script lang="ts">
export default {
  name: 'Item',

  data() {
    return {
      buy: JSON.parse(localStorage.getItem('buyItem')),
      read: JSON.parse(localStorage.getItem('readItem'))
    }
  },

  props: {
    title: String,
    cover: String,
    collection: String
  },

  mounted() {
    if (localStorage.getItem('buyItem')) this.buy = JSON.parse(localStorage.getItem('buyItem'));
    if (localStorage.getItem('readItem')) this.read = JSON.parse(localStorage.getItem('readItem'));
  },

  methods: {
    toggleBuy() {
      this.buy = !this.buy
      localStorage.setItem('buyItem', JSON.stringify(this.buy))
    },
    toggleRead() {
      this.read = !this.read
      localStorage.setItem('readItem', JSON.stringify(this.read))
    }
  }
}
</script>

父组件中列出了我的漫画数据:

<template>
  <div class="bg-white shadow-lg rounded-xl px-8 pb-8 pt-4">

    <h2 class="ml-2 md:ml-8 mb-4 uppercase text-xl font-bold leading-7">
      New 52
    </h2>

    <div class="mx-auto">
      <div class="flex flex-wrap justify-center sm:justify-between">
        <Item
          v-for="item in renaissance"
          :key="item.id"
          :title="item.title"
          :cover="item.cover"
          :collection="item.collection"
        />
      </div>
    </div>
  </div>
</template>

<script lang="ts">
export default {
  name: 'Renaissance',

  data() {
    return {
      renaissance: [
        {
          key: 1,
          cover: "https://bdi.dlpdomain.com/album/9782365770415/couv/M385x862/batman-tome-1-la-cour-des-hiboux.jpg",
          title: "Tome 1: La Cour de Hiboux",
          collection: "new 52"
        },
        {
          key: 2,
          cover: "https://bdi.dlpdomain.com/album/9782365772068/couv/I500x800/batman-tome-2.jpg",
          title: "Tome 2: la nuit des hiboux",
          collection: "new 52"
        },
        {
          key: 3,
          cover: "https://bdi.dlpdomain.com/album/9791026815327/couv/M385x862/batman-amp-robin-integrale-tome-1.jpg",
          title: "Tome 1",
          collection: "batman & robin"
        },
        // there is more...
      ]
    }
  }
}
</script>

如果您进行以下更改,它应该会起作用。

  1. 您的 renaissance 数组当前没有名为 id 的 属性,因此我会将您的 key 更改为 id 这样 :key="item.id" 有效

  2. id 传递给您的 Item 组件,即 :id="item.id"

  3. 在您的 Item 组件中添加了一个道具,即 id: Number

  4. 将您的 localStorage 密钥更改为 "item-" + this.id + "-buy""item-" + this.id + "-sell"

现在每次买卖都会有一个不同的localStorage key,区别在于id

我强烈推荐使用 Vuex,从长远来看,它会让事情变得更容易 运行 What is Vuex?