hookehuyr

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

迁移购物车上下文逻辑,从React的CartContext.jsx迁移到Vue的cart.js,以支持Vue项目的需求。新的实现使用Vue的ref和provide/inject API,并保留了原有的功能,如购物车管理、本地存储同步和结账流程。
1 -import React, { createContext, useContext, useState, useEffect } from 'react';
2 -import { useNavigate } from 'react-router-dom';
3 -
4 -// Create a context for the cart
5 -const CartContext = createContext();
6 -
7 -// Custom hook to use the cart context
8 -export const useCart = () => {
9 - const context = useContext(CartContext);
10 - if (!context) {
11 - throw new Error('useCart must be used within a CartProvider');
12 - }
13 - return context;
14 -};
15 -
16 -// Cart provider component
17 -export const CartProvider = ({ children }) => {
18 - const [cartItems, setCartItems] = useState([]);
19 - const navigate = useNavigate();
20 -
21 - // Load cart from localStorage on component mount
22 - useEffect(() => {
23 - const storedCart = localStorage.getItem('cart');
24 - if (storedCart) {
25 - try {
26 - setCartItems(JSON.parse(storedCart));
27 - } catch (error) {
28 - console.error('Failed to parse cart from localStorage:', error);
29 - // Reset cart if there's an error
30 - localStorage.removeItem('cart');
31 - }
32 - }
33 - }, []);
34 -
35 - // Save cart to localStorage whenever it changes
36 - useEffect(() => {
37 - localStorage.setItem('cart', JSON.stringify(cartItems));
38 - }, [cartItems]);
39 -
40 - // Add an item to the cart
41 - const addToCart = (item) => {
42 - setCartItems(prevItems => {
43 - // Check if item already exists in cart
44 - const existingItemIndex = prevItems.findIndex(i =>
45 - i.id === item.id && i.type === item.type
46 - );
47 -
48 - if (existingItemIndex >= 0) {
49 - // Item exists, update the quantity
50 - const updatedItems = [...prevItems];
51 - updatedItems[existingItemIndex] = {
52 - ...updatedItems[existingItemIndex],
53 - quantity: updatedItems[existingItemIndex].quantity + 1
54 - };
55 - return updatedItems;
56 - } else {
57 - // Item doesn't exist, add it with quantity 1
58 - return [...prevItems, { ...item, quantity: 1 }];
59 - }
60 - });
61 - };
62 -
63 - // Remove an item from the cart
64 - const removeFromCart = (itemId, itemType) => {
65 - setCartItems(prevItems =>
66 - prevItems.filter(item => !(item.id === itemId && item.type === itemType))
67 - );
68 - };
69 -
70 - // Update quantity of an item in the cart
71 - const updateQuantity = (itemId, itemType, quantity) => {
72 - if (quantity < 1) return;
73 -
74 - setCartItems(prevItems =>
75 - prevItems.map(item =>
76 - (item.id === itemId && item.type === itemType)
77 - ? { ...item, quantity }
78 - : item
79 - )
80 - );
81 - };
82 -
83 - // Clear the entire cart
84 - const clearCart = () => {
85 - setCartItems([]);
86 - };
87 -
88 - // Get the number of items in cart
89 - const getItemCount = () => {
90 - return cartItems.reduce((total, item) => total + item.quantity, 0);
91 - };
92 -
93 - // Calculate the total price of items in the cart
94 - const getTotalPrice = () => {
95 - return cartItems.reduce(
96 - (total, item) => total + (item.price * item.quantity),
97 - 0
98 - );
99 - };
100 -
101 - // Proceed to checkout
102 - const proceedToCheckout = () => {
103 - if (cartItems.length > 0) {
104 - navigate('/checkout');
105 - }
106 - };
107 -
108 - // Handle the checkout process
109 - const handleCheckout = (userData) => {
110 - // In a real application, this would send the order to a backend
111 - console.log('Processing order with data:', { items: cartItems, userData });
112 -
113 - // Simulating successful checkout
114 - return new Promise((resolve) => {
115 - setTimeout(() => {
116 - clearCart();
117 - resolve({ success: true, orderId: 'ORD-' + Date.now() });
118 - }, 1500);
119 - });
120 - };
121 -
122 - // Values to provide in the context
123 - const value = {
124 - cartItems,
125 - addToCart,
126 - removeFromCart,
127 - updateQuantity,
128 - clearCart,
129 - getItemCount,
130 - getTotalPrice,
131 - proceedToCheckout,
132 - handleCheckout
133 - };
134 -
135 - return (
136 - <CartContext.Provider value={value}>
137 - {children}
138 - </CartContext.Provider>
139 - );
140 -};
...\ No newline at end of file ...\ No newline at end of file
1 +import { ref, provide, inject, watchEffect } from 'vue'
2 +import { useRouter } from 'vue-router'
3 +
4 +const CartSymbol = Symbol()
5 +
6 +export function provideCart() {
7 + const router = useRouter()
8 + const cartItems = ref([])
9 +
10 + // 从localStorage加载购物车数据
11 + try {
12 + const storedCart = localStorage.getItem('cart')
13 + if (storedCart) {
14 + cartItems.value = JSON.parse(storedCart)
15 + }
16 + } catch (error) {
17 + console.error('Failed to parse cart from localStorage:', error)
18 + localStorage.removeItem('cart')
19 + }
20 +
21 + // 监听购物车变化并保存到localStorage
22 + watchEffect(() => {
23 + localStorage.setItem('cart', JSON.stringify(cartItems.value))
24 + })
25 +
26 + // 添加商品到购物车
27 + function addToCart(item) {
28 + const existingItemIndex = cartItems.value.findIndex(
29 + i => i.id === item.id && i.type === item.type
30 + )
31 +
32 + if (existingItemIndex >= 0) {
33 + const updatedItems = [...cartItems.value]
34 + updatedItems[existingItemIndex] = {
35 + ...updatedItems[existingItemIndex],
36 + quantity: updatedItems[existingItemIndex].quantity + 1
37 + }
38 + cartItems.value = updatedItems
39 + } else {
40 + cartItems.value = [...cartItems.value, { ...item, quantity: 1 }]
41 + }
42 + }
43 +
44 + // 从购物车移除商品
45 + function removeFromCart(itemId, itemType) {
46 + cartItems.value = cartItems.value.filter(
47 + item => !(item.id === itemId && item.type === itemType)
48 + )
49 + }
50 +
51 + // 更新商品数量
52 + function updateQuantity(itemId, itemType, quantity) {
53 + if (quantity < 1) return
54 +
55 + cartItems.value = cartItems.value.map(item =>
56 + item.id === itemId && item.type === itemType
57 + ? { ...item, quantity }
58 + : item
59 + )
60 + }
61 +
62 + // 清空购物车
63 + function clearCart() {
64 + cartItems.value = []
65 + }
66 +
67 + // 获取购物车商品总数
68 + function getItemCount() {
69 + return cartItems.value.reduce((total, item) => total + item.quantity, 0)
70 + }
71 +
72 + // 计算购物车总价
73 + function getTotalPrice() {
74 + return cartItems.value.reduce(
75 + (total, item) => total + item.price * item.quantity,
76 + 0
77 + )
78 + }
79 +
80 + // 跳转到结账页面
81 + function proceedToCheckout() {
82 + if (cartItems.value.length > 0) {
83 + router.push('/checkout')
84 + }
85 + }
86 +
87 + // 处理结账流程
88 + function handleCheckout(userData) {
89 + console.warn('Processing order with data:', { items: cartItems.value, userData })
90 +
91 + return new Promise((resolve) => {
92 + setTimeout(() => {
93 + clearCart()
94 + resolve({ success: true, orderId: 'ORD-' + Date.now() })
95 + }, 1500)
96 + })
97 + }
98 +
99 + const cart = {
100 + items: cartItems,
101 + addToCart,
102 + removeFromCart,
103 + updateQuantity,
104 + clearCart,
105 + getItemCount,
106 + getTotalPrice,
107 + proceedToCheckout,
108 + handleCheckout
109 + }
110 +
111 + provide(CartSymbol, cart)
112 +
113 + return cart
114 +}
115 +
116 +export function useCart() {
117 + const cart = inject(CartSymbol)
118 + if (!cart) {
119 + throw new Error('useCart() must be used within a component that has called provideCart()')
120 + }
121 + return cart
122 +}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.