组件层次划分
- 顶层组件:一般为
App
组件,作为整个应用的入口,负责初始化应用,设置全局样式、路由等。例如:
import React from'react';
import { BrowserRouter as Router } from'react-router-dom';
import Routes from './Routes';
function App() {
return (
<Router>
<Routes />
</Router>
);
}
export default App;
- 路由组件:基于 React Router 等路由库,负责不同页面(模块)的导航和渲染。如:
import React from'react';
import { Routes, Route } from'react-router-dom';
import Home from './Home';
import ProductList from './ProductList';
import Cart from './Cart';
import Login from './Login';
function RoutesConfig() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<ProductList />} />
<Route path="/cart" element={<Cart />} />
<Route path="/login" element={<Login />} />
</Routes>
);
}
export default RoutesConfig;
- 模块组件:
- 商品展示模块:
- ProductList:负责展示商品列表,可能从后端获取数据并渲染
ProductItem
组件。
import React, { useEffect, useState } from'react';
import ProductItem from './ProductItem';
function ProductList() {
const [products, setProducts] = useState([]);
useEffect(() => {
// 模拟从后端获取商品数据
fetch('/api/products')
.then(response => response.json())
.then(data => setProducts(data));
}, []);
return (
<div>
{products.map(product => (
<ProductItem key={product.id} product={product} />
))}
</div>
);
}
export default ProductList;
- ProductItem:展示单个商品的详细信息,如图片、价格、名称等。
import React from'react';
function ProductItem({ product }) {
return (
<div>
<img src={product.imageUrl} alt={product.name} />
<h3>{product.name}</h3>
<p>{product.price}</p>
</div>
);
}
export default ProductItem;
- 购物车模块:
- Cart:管理购物车的整体状态,如购物车中的商品列表、总价计算等。
import React, { useState, useEffect } from'react';
import CartItem from './CartItem';
function Cart() {
const [cartItems, setCartItems] = useState([]);
const [totalPrice, setTotalPrice] = useState(0);
useEffect(() => {
// 从本地存储或后端获取购物车数据
const storedCart = JSON.parse(localStorage.getItem('cart')) || [];
setCartItems(storedCart);
calculateTotalPrice(storedCart);
}, []);
const calculateTotalPrice = (items) => {
const total = items.reduce((acc, item) => acc + item.price * item.quantity, 0);
setTotalPrice(total);
};
return (
<div>
{cartItems.map(item => (
<CartItem key={item.id} item={item} onQuantityChange={calculateTotalPrice} />
))}
<p>Total Price: {totalPrice}</p>
</div>
);
}
export default Cart;
- CartItem:展示购物车中单个商品的信息,包括数量调整等交互。
import React, { useState } from'react';
function CartItem({ item, onQuantityChange }) {
const [quantity, setQuantity] = useState(item.quantity);
const handleQuantityChange = (e) => {
const newQuantity = parseInt(e.target.value, 10);
setQuantity(newQuantity);
onQuantityChange([{...item, quantity: newQuantity }]);
};
return (
<div>
<img src={item.imageUrl} alt={item.name} />
<h3>{item.name}</h3>
<input type="number" value={quantity} onChange={handleQuantityChange} />
<p>{item.price * quantity}</p>
</div>
);
}
export default CartItem;
- 用户登录模块:
import React, { useState } from'react';
function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
// 模拟登录请求
console.log(`Logging in with username: ${username}, password: ${password}`);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Username" value={username} onChange={(e) => setUsername(e.target.value)} />
<input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} />
<button type="submit">Login</button>
</form>
);
}
export default Login;
组件状态管理
- 局部状态:对于只影响组件自身渲染的状态,使用
useState
钩子。如 ProductList
组件中获取商品数据的状态,CartItem
组件中商品数量的状态。
- 共享状态:
- Context API:适用于一些不适合用 Redux 等复杂状态管理库的轻量级共享状态。例如,如果有一个全局的用户登录状态,可以通过 Context 来共享。
import React, { createContext, useState, useEffect } from'react';
const UserContext = createContext();
function UserProvider({ children }) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
// 从本地存储判断用户是否已登录
const isUserLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
setIsLoggedIn(isUserLoggedIn);
}, []);
return (
<UserContext.Provider value={{ isLoggedIn, setIsLoggedIn }}>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
- Redux:对于大型应用中复杂的共享状态管理,如购物车的全局状态(商品列表、总价等在多个组件间共享且会被不同组件修改),使用 Redux。
- Action:定义各种操作,如添加商品到购物车、修改商品数量等。
const ADD_TO_CART = 'ADD_TO_CART';
const UPDATE_QUANTITY = 'UPDATE_QUANTITY';
export const addToCart = (product) => ({
type: ADD_TO_CART,
payload: product
});
export const updateQuantity = (productId, quantity) => ({
type: UPDATE_QUANTITY,
payload: { productId, quantity }
});
const initialState = {
cartItems: [],
totalPrice: 0
};
const cartReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_CART:
return {
...state,
cartItems: [...state.cartItems, action.payload],
totalPrice: state.totalPrice + action.payload.price
};
case UPDATE_QUANTITY:
const { productId, quantity } = action.payload;
const updatedCartItems = state.cartItems.map(item => {
if (item.id === productId) {
return {...item, quantity };
}
return item;
});
const newTotalPrice = updatedCartItems.reduce((acc, item) => acc + item.price * item.quantity, 0);
return {
...state,
cartItems: updatedCartItems,
totalPrice: newTotalPrice
};
default:
return state;
}
};
export default cartReducer;
- Store:创建 Redux store 并将 reducer 传入。
import { createStore } from'redux';
import cartReducer from './cartReducer';
const store = createStore(cartReducer);
export default store;
- Connect Components:在组件中使用
react - redux
的 connect
或 useSelector
、useDispatch
钩子来连接组件与 Redux store。如在 Cart
组件中:
import React from'react';
import { useSelector, useDispatch } from'react-redux';
import { addToCart, updateQuantity } from './actions';
function Cart() {
const cartItems = useSelector(state => state.cartItems);
const totalPrice = useSelector(state => state.totalPrice);
const dispatch = useDispatch();
const handleAddToCart = (product) => {
dispatch(addToCart(product));
};
const handleQuantityChange = (productId, quantity) => {
dispatch(updateQuantity(productId, quantity));
};
return (
<div>
{cartItems.map(item => (
<div key={item.id}>
<img src={item.imageUrl} alt={item.name} />
<h3>{item.name}</h3>
<input type="number" value={item.quantity} onChange={(e) => handleQuantityChange(item.id, parseInt(e.target.value, 10))} />
<p>{item.price * item.quantity}</p>
</div>
))}
<p>Total Price: {totalPrice}</p>
</div>
);
}
export default Cart;
组件间通信
- 父子通信:通过 props 传递数据和函数。父组件向子组件传递数据,如
ProductList
向 ProductItem
传递商品数据,Cart
向 CartItem
传递购物车商品数据及更新总价的函数。
- 子父通信:子组件通过父组件传递的函数回调来通知父组件状态变化。例如
CartItem
通过 onQuantityChange
回调通知 Cart
组件更新总价。
- 跨层级通信:
- 使用 Context:如前面提到的通过
UserContext
共享用户登录状态,任何层级的组件都可以订阅这个 Context 获取或修改登录状态。
- Redux:通过 Redux,不同层级的组件都可以通过 dispatch Action 来修改共享状态,从而实现通信。例如,
ProductItem
组件可以 dispatch addToCart
Action,Cart
组件通过订阅 Redux store 来响应这个状态变化并更新自身渲染。
关键技术点
- 路由管理:合理使用 React Router 配置路由,确保不同模块页面的正确导航和渲染,同时处理好路由参数传递等问题。
- 状态管理库选择:根据应用规模和复杂度选择合适的状态管理方案,如 Context API 或 Redux。对于简单共享状态,Context API 足够;对于复杂的、多组件交互的共享状态,Redux 更合适。
- 性能优化:
- Memoization:使用
React.memo
包裹纯函数组件,避免不必要的重新渲染。例如 ProductItem
、CartItem
等组件,当 props 没有变化时不重新渲染。
- Virtualization:对于商品列表等可能有大量数据的组件,使用 React Virtualized 或 React Window 等库进行虚拟化渲染,提高性能。
- 代码组织与可维护性:采用清晰的文件夹结构,将不同模块的组件、状态管理代码等分开存放,遵循一定的命名规范和代码风格,提高代码的可读性和可维护性。例如,将商品展示模块的相关文件放在
product
文件夹,购物车模块的文件放在 cart
文件夹等。