Vuex+LocalStorage删除选中食谱异常:误删最新添加项问题
问题描述
我正在开发一款食谱应用,尝试创建一个按钮,从结合LocalStorage的Vuex中删除已添加的食谱。但当前点击删除按钮时,并未删除选中的目标食谱,反而删除了Vuex数组中最新添加的食谱。
Vuex Store 代码
state: { recipes: [ { slug: '', title: '', description: '', ingredients: [], method: [] }, { slug: '', title: '', description: '', ingredients: [], method: [] }, ] }, getters: {}, mutations: { loadStore() { if(localStorage.getItem('store')) { try { this.replaceState(JSON.parse(localStorage.getItem('store'))); } catch(e) { console.log('Could not initialize store', e); } } }, ADD_RECIPE (state, recipe){ state.recipes.push(recipe) }, // 这是删除方法 delete_Recipe(state, recipe){ let index = state.recipes.indexOf(recipe); state.recipes.splice(index,1); }, },
组件代码
<template> <div class="recipe"> <router-link to="/">< Back</router-link> <h1>{{ recipe.title }}</h1> <p class="desc">{{recipe.description}}</p> <hr /> <div class="ingredients"> <h3> Ingredients</h3> <ul> <li v-for="(ingredient, i) in recipe.ingredients" :key="i"> {{ingredient }} </li> </ul> </div> <hr /> <div class="method"> <h3> Instructions</h3> <ol> <li v-for="(step, i) in recipe.method" :key="i"> <span v-html="cleanText(step)"></span> </li> </ol> </div> <button @click="deleteRecipe">Delete Recipe</button> </div> </template> <script> import $store from '../store' export default { setup(){ const deleteRecipe = () => { $store.commit('delete_Recipe') } return {deleteRecipe} }, computed: { recipe(){ return this.$store.state.recipes.find(recipe => recipe.slug === this.$route.params.slug) } } } </script>
解决方案
问题根源
- 未传递删除目标:调用
delete_Recipemutation时没有传入要删除的recipe对象,导致recipe参数为undefined。state.recipes.indexOf(undefined)返回-1,而splice(-1, 1)会删除数组最后一个元素,这就是为什么删了最新添加的食谱。 - 引用匹配不可靠:即使传入了recipe对象,
indexOf依赖对象引用完全一致才会找到索引。但从LocalStorage加载的对象是重新解析的新对象,和组件中find出来的对象引用不同,会导致indexOf返回-1,同样触发删除最后一个元素的问题。
修改步骤
1. 组件中传递删除目标
修改组件的setup部分,正确获取当前recipe并传递给mutation:
<script> import { useStore, useRoute } from 'vuex' import { computed } from 'vue' export default { setup(){ const store = useStore() const route = useRoute() // 在setup中用computed获取当前食谱 const recipe = computed(() => store.state.recipes.find(r => r.slug === route.params.slug)) const deleteRecipe = () => { // 传递当前食谱给mutation if(recipe.value) { store.commit('delete_Recipe', recipe.value) } } return {deleteRecipe, recipe} } } </script>
2. 改进Vuex的删除逻辑
改用唯一标识(比如slug)查找索引,避免引用匹配问题:
delete_Recipe(state, recipe){ // 通过slug查找目标食谱的索引 const index = state.recipes.findIndex(r => r.slug === recipe.slug); // 确认找到索引后再删除 if(index !== -1) { state.recipes.splice(index, 1); } },
3. 确保LocalStorage同步更新
每次修改store后要同步到LocalStorage,可通过订阅mutation实现:
// 在创建store后添加订阅逻辑 const store = createStore({ // ...你的state、mutations等配置 }) store.subscribe((mutation, state) => { localStorage.setItem('store', JSON.stringify(state)); })
内容的提问来源于stack exchange,提问作者user19498535
相关产品推荐
相关产品推荐

