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>
如果您进行以下更改,它应该会起作用。
您的 renaissance
数组当前没有名为 id
的 属性,因此我会将您的 key
更改为 id
这样 :key="item.id"
有效
将 id
传递给您的 Item
组件,即 :id="item.id"
在您的 Item
组件中添加了一个道具,即 id: Number
将您的 localStorage 密钥更改为 "item-" + this.id + "-buy"
和 "item-" + this.id + "-sell"
现在每次买卖都会有一个不同的localStorage key,区别在于id
。
我强烈推荐使用 Vuex,从长远来看,它会让事情变得更容易 运行 What is Vuex?。
我在一个项目中,我在数据中硬编码一个列表(一些 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>
如果您进行以下更改,它应该会起作用。
您的
renaissance
数组当前没有名为id
的 属性,因此我会将您的key
更改为id
这样:key="item.id"
有效将
id
传递给您的Item
组件,即:id="item.id"
在您的
Item
组件中添加了一个道具,即id: Number
将您的 localStorage 密钥更改为
"item-" + this.id + "-buy"
和"item-" + this.id + "-sell"
现在每次买卖都会有一个不同的localStorage key,区别在于id
。
我强烈推荐使用 Vuex,从长远来看,它会让事情变得更容易 运行 What is Vuex?。