hookehuyr

refactor(cart): 将购物车逻辑从React迁移到Vue

迁移购物车上下文逻辑,从React的CartContext.jsx迁移到Vue的cart.js,以支持Vue项目的需求。新的实现使用Vue的ref和provide/inject API,并保留了原有的功能,如购物车管理、本地存储同步和结账流程。
import React, { createContext, useContext, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
// Create a context for the cart
const CartContext = createContext();
// Custom hook to use the cart context
export const useCart = () => {
const context = useContext(CartContext);
if (!context) {
throw new Error('useCart must be used within a CartProvider');
}
return context;
};
// Cart provider component
export const CartProvider = ({ children }) => {
const [cartItems, setCartItems] = useState([]);
const navigate = useNavigate();
// Load cart from localStorage on component mount
useEffect(() => {
const storedCart = localStorage.getItem('cart');
if (storedCart) {
try {
setCartItems(JSON.parse(storedCart));
} catch (error) {
console.error('Failed to parse cart from localStorage:', error);
// Reset cart if there's an error
localStorage.removeItem('cart');
}
}
}, []);
// Save cart to localStorage whenever it changes
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cartItems));
}, [cartItems]);
// Add an item to the cart
const addToCart = (item) => {
setCartItems(prevItems => {
// Check if item already exists in cart
const existingItemIndex = prevItems.findIndex(i =>
i.id === item.id && i.type === item.type
);
if (existingItemIndex >= 0) {
// Item exists, update the quantity
const updatedItems = [...prevItems];
updatedItems[existingItemIndex] = {
...updatedItems[existingItemIndex],
quantity: updatedItems[existingItemIndex].quantity + 1
};
return updatedItems;
} else {
// Item doesn't exist, add it with quantity 1
return [...prevItems, { ...item, quantity: 1 }];
}
});
};
// Remove an item from the cart
const removeFromCart = (itemId, itemType) => {
setCartItems(prevItems =>
prevItems.filter(item => !(item.id === itemId && item.type === itemType))
);
};
// Update quantity of an item in the cart
const updateQuantity = (itemId, itemType, quantity) => {
if (quantity < 1) return;
setCartItems(prevItems =>
prevItems.map(item =>
(item.id === itemId && item.type === itemType)
? { ...item, quantity }
: item
)
);
};
// Clear the entire cart
const clearCart = () => {
setCartItems([]);
};
// Get the number of items in cart
const getItemCount = () => {
return cartItems.reduce((total, item) => total + item.quantity, 0);
};
// Calculate the total price of items in the cart
const getTotalPrice = () => {
return cartItems.reduce(
(total, item) => total + (item.price * item.quantity),
0
);
};
// Proceed to checkout
const proceedToCheckout = () => {
if (cartItems.length > 0) {
navigate('/checkout');
}
};
// Handle the checkout process
const handleCheckout = (userData) => {
// In a real application, this would send the order to a backend
console.log('Processing order with data:', { items: cartItems, userData });
// Simulating successful checkout
return new Promise((resolve) => {
setTimeout(() => {
clearCart();
resolve({ success: true, orderId: 'ORD-' + Date.now() });
}, 1500);
});
};
// Values to provide in the context
const value = {
cartItems,
addToCart,
removeFromCart,
updateQuantity,
clearCart,
getItemCount,
getTotalPrice,
proceedToCheckout,
handleCheckout
};
return (
<CartContext.Provider value={value}>
{children}
</CartContext.Provider>
);
};
\ No newline at end of file
import { ref, provide, inject, watchEffect } from 'vue'
import { useRouter } from 'vue-router'
const CartSymbol = Symbol()
export function provideCart() {
const router = useRouter()
const cartItems = ref([])
// 从localStorage加载购物车数据
try {
const storedCart = localStorage.getItem('cart')
if (storedCart) {
cartItems.value = JSON.parse(storedCart)
}
} catch (error) {
console.error('Failed to parse cart from localStorage:', error)
localStorage.removeItem('cart')
}
// 监听购物车变化并保存到localStorage
watchEffect(() => {
localStorage.setItem('cart', JSON.stringify(cartItems.value))
})
// 添加商品到购物车
function addToCart(item) {
const existingItemIndex = cartItems.value.findIndex(
i => i.id === item.id && i.type === item.type
)
if (existingItemIndex >= 0) {
const updatedItems = [...cartItems.value]
updatedItems[existingItemIndex] = {
...updatedItems[existingItemIndex],
quantity: updatedItems[existingItemIndex].quantity + 1
}
cartItems.value = updatedItems
} else {
cartItems.value = [...cartItems.value, { ...item, quantity: 1 }]
}
}
// 从购物车移除商品
function removeFromCart(itemId, itemType) {
cartItems.value = cartItems.value.filter(
item => !(item.id === itemId && item.type === itemType)
)
}
// 更新商品数量
function updateQuantity(itemId, itemType, quantity) {
if (quantity < 1) return
cartItems.value = cartItems.value.map(item =>
item.id === itemId && item.type === itemType
? { ...item, quantity }
: item
)
}
// 清空购物车
function clearCart() {
cartItems.value = []
}
// 获取购物车商品总数
function getItemCount() {
return cartItems.value.reduce((total, item) => total + item.quantity, 0)
}
// 计算购物车总价
function getTotalPrice() {
return cartItems.value.reduce(
(total, item) => total + item.price * item.quantity,
0
)
}
// 跳转到结账页面
function proceedToCheckout() {
if (cartItems.value.length > 0) {
router.push('/checkout')
}
}
// 处理结账流程
function handleCheckout(userData) {
console.warn('Processing order with data:', { items: cartItems.value, userData })
return new Promise((resolve) => {
setTimeout(() => {
clearCart()
resolve({ success: true, orderId: 'ORD-' + Date.now() })
}, 1500)
})
}
const cart = {
items: cartItems,
addToCart,
removeFromCart,
updateQuantity,
clearCart,
getItemCount,
getTotalPrice,
proceedToCheckout,
handleCheckout
}
provide(CartSymbol, cart)
return cart
}
export function useCart() {
const cart = inject(CartSymbol)
if (!cart) {
throw new Error('useCart() must be used within a component that has called provideCart()')
}
return cart
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.