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

Vue 3 Composition API 实现localStorage添加购物车项刷新重置及报错问题求解

问题原因

  • 初始代码逻辑缺陷:组件初始化时cartItems固定被赋值为空响应式数组,页面刷新后不会读取localStorage中已存储的购物车数据,新增商品时会用空数组拼接新数据,覆盖localStorage原有内容。
  • 修正代码的逻辑错误:直接将localStorage取出的JSON字符串赋值给cartItems变量,覆盖了原有的ref响应式实例,且没有对字符串做JSON解析,此时cartItems为普通字符串,不存在value属性,调用cartItems.value.push自然会抛出未找到push方法的错误。
  • 原有代码还存在一个隐性问题:onMounted(getProduct(props.id))写法错误,会立即执行getProduct方法而非组件挂载后执行,需要包一层箭头函数。

修复方案

直接修改商品详情页代码即可解决问题,修正后完整代码如下:

export default {
    props: {
        id: {
            required: true,
            type: String
        }
    },

    setup(props) {
        const { product, getProduct } = useProducts()
        // 修复onMounted执行时机错误
        onMounted(() => getProduct(props.id))

        // 初始化响应式购物车数组
        const cartItems = ref([])
        // 读取本地已存储的购物车数据
        const savedCart = window.localStorage.getItem('CART')
        if (savedCart) {
            try {
                // 仅给ref的value属性赋值,不替换ref实例
                cartItems.value = JSON.parse(savedCart)
            } catch (err) {
                // 本地存储数据损坏时清空异常数据
                window.localStorage.removeItem('CART')
            }
        }

        function addProductToCart(product) {
            // 可按需添加同商品数量累加逻辑,不需要可以直接保留原有push逻辑
            const existItem = cartItems.value.find(item => item.id === product.id)
            if (existItem) {
                existItem.quantity = (existItem.quantity || 1) + 1
            } else {
                cartItems.value.push({...product, quantity: 1})
            }
            window.localStorage.setItem('CART', JSON.stringify(cartItems.value))
            console.log(JSON.parse(localStorage.getItem('CART')));
        }

        return {
            addProductToCart,
            product
        }
    }
}

优化建议

如果后续需要在多个页面复用购物车逻辑、保证购物车状态全局同步,可以将购物车逻辑抽为独立的Composition API可复用函数:

  1. 新建composables/useCart.js文件,代码如下:
import { ref } from 'vue'

// 全局唯一的购物车响应式数据
const cartItems = ref([])
// 初始化时读取一次本地存储数据
const savedCart = window.localStorage.getItem('CART')
if (savedCart) {
    try {
        cartItems.value = JSON.parse(savedCart)
    } catch (err) {
        window.localStorage.removeItem('CART')
    }
}

export default function useCart() {
    const addProductToCart = (product) => {
        const existItem = cartItems.value.find(item => item.id === product.id)
        if (existItem) {
            existItem.quantity = (existItem.quantity || 1) + 1
        } else {
            cartItems.value.push({...product, quantity: 1})
        }
        window.localStorage.setItem('CART', JSON.stringify(cartItems.value))
    }

    const clearCart = () => {
        cartItems.value = []
        window.localStorage.removeItem('CART')
    }

    return {
        cartItems,
        addProductToCart,
        clearCart
    }
}
  1. 在组件中直接引入使用即可,无需重复编写购物车存储逻辑:
import useCart from '@/composables/useCart'

export default {
    props: {
        id: {
            required: true,
            type: String
        }
    },
    setup(props) {
        const { product, getProduct } = useProducts()
        const { addProductToCart } = useCart()
        onMounted(() => getProduct(props.id))
        
        return {
            addProductToCart,
            product
        }
    }
}

内容的提问来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:06:07