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可复用函数:
- 新建
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 } }
- 在组件中直接引入使用即可,无需重复编写购物车存储逻辑:
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
相关产品推荐
相关产品推荐

