Nuxt项目使用Vuex mutation实现迷你购物车商品数量递增功能求助
需修改的核心问题
- 原
increasemutation未接收商品参数、未定位到购物车中对应商品就直接修改属性,且state.cart是数组,不存在quantity属性 - 组件调用
increase时仅传了商品id,未传完整商品对象 - 原删除/减少逻辑中直接将商品对象作为
splice的第一个参数,splice要求第一个参数为数组下标,会导致删除逻辑失效 - v-for绑定的key为完整商品对象,不符合Vue规范
代码修改
1. Vue组件调整
<template> <div class="bg-white shadow-lg rounded-md absolute right-16"> <!-- 把key改成商品唯一id --> <div class="grid grid-cols-2 m-5 mt-9" v-for="carts in cart" :key="carts.id" > <img class="w-24 rounded" :src="carts.img" alt="" /> <div class="grid grid-rows-2"> <strong class="tracking-wider text-center text-lg font-bold">{{ carts.title }}</strong> <div class="grid grid-cols-4 text-center"> <button class=" text-lg font-bold text-purple-500 bg-purple-200 rounded transition-all hover:bg-purple-300 " type="button" <!-- 传完整商品对象,不是id --> v-on:click="increase(carts)" > + </button> <p class="text-gray-500 mt-0.5 leading-9 font-normal"> {{ carts.quantity }} </p> <button class=" text-lg font-bold text-purple-500 bg-purple-200 rounded transition-all hover:bg-purple-300 " type="button" v-on:click="decrease(carts)" > - </button> <button class=" bg-gray-200 rounded p-2 tracking-wider font-bold ml-4 text-gray-500 transition-all hover:bg-gray-300 " v-on:click="removeItem(carts)" > 🗑️ </button> </div> <p class=" text-base tracking-wider mt-2 text-center text-gray-500 font-medium " > ${{ carts.price }} </p> </div> </div> <div class="flex mx-5 my-8 justify-between"> <span class=" tracking-wider text-lg p-4 font-medium justify-center align-middle " >Total: ${{ total }}</span > <button v-on:click="clearCart" type="button" href="" class=" bg-red-400 transition-all hover:bg-red-500 p-4 rounded tracking-wider text-white text-medium font-medium leading-none " > Clear Cart </button> </div> </div> </template> <script> import { mapGetters } from "vuex"; export default { computed: mapGetters({ cart: "cart", total: "total", }), methods: { removeItem(carts) { this.$store.dispatch("removeItem", carts); }, // 统一走action调用,和其他方法逻辑对齐 increase(carts) { this.$store.dispatch("increase", carts); }, decrease(carts) { this.$store.dispatch("decrease", carts); }, clearCart() { this.$store.dispatch("clearCart"); }, }, }; </script>
2. Store调整
export const state = () => ({ cart: [], breeds: [ // 原有商品列表内容保持不变,此处省略 ] }); export const getters = { // 重复的checkCart getter可删除,和cart功能完全一致 cart(state) { return state.cart; }, total(state) { let total = 0; for (let carts of state.cart) { // price是字符串,转数字避免计算错误 total += Number(carts.price) * carts.quantity; } return total.toFixed(2); }, cartTotal(state) { return state.cart.length; }, getPiggyById: (state) => (id) => { return state.breeds.find(breed => breed.id == id) } } export const mutations = { pushToCart(state, breed) { state.cart.push(breed) }, removeItem(state, carts) { // 先找对应商品的下标再删除 const index = state.cart.findIndex(item => item.id === carts.id) if (index > -1) state.cart.splice(index, 1); }, increase(state, carts) { // 找到对应商品,数量加1 const target = state.cart.find(item => item.id === carts.id) if (target) target.quantity += 1 }, decrease(state, carts) { const target = state.cart.find(item => item.id === carts.id) if (!target) return if (target.quantity > 1) { target.quantity -= 1; } else { const index = state.cart.findIndex(item => item.id === carts.id) if (index > -1) state.cart.splice(index, 1); } }, clearCart(state) { state.cart.splice(0, state.cart.length); }, }; export const actions = { pushToCart({ commit }, breed) { commit("pushToCart", breed) }, removeItem({ commit }, carts) { commit("removeItem", carts) }, // 新增increase的action,统一操作入口 increase({ commit }, carts) { commit("increase", carts) }, decrease({ commit }, carts) { commit("decrease", carts) }, clearCart({ commit }) { commit("clearCart") }, }
额外优化建议
- 商品价格建议存储为数字类型,避免后续计算频繁转类型
- 加入购物车逻辑建议先判断商品是否已在购物车,存在则直接加数量,不用重复push新对象
- 可将购物车操作的常用逻辑封装成Vuex的辅助函数,减少重复代码
内容的提问来源于stack exchange,提问作者OrangeSoLlama
相关产品推荐
相关产品推荐

