You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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="/">&lt; 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>
解决方案

问题根源

  1. 未传递删除目标:调用delete_Recipe mutation时没有传入要删除的recipe对象,导致recipe参数为undefined。state.recipes.indexOf(undefined)返回-1,而splice(-1, 1)会删除数组最后一个元素,这就是为什么删了最新添加的食谱。
  2. 引用匹配不可靠:即使传入了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:05:28