元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
React基础
▶
环境搭建
使用Create React App
Webpack基础配置
Babel转换配置
▶
JSX核心
JSX语法基础
JSX表达式使用
JSX与HTML差异
▶
组件入门
函数组件编写
类组件结构
组件组合模式
▶
核心概念
▶
Props机制
Props传递与接收
PropTypes类型检查
默认Props设置
▶
State管理
useState使用
setState机制
状态提升
▶
生命周期
类组件生命周期
useEffect使用
依赖项数组作用
▶
进阶实践
▶
路由管理
React Router安装
基本路由配置
动态路由参数
▶
状态管理
Context API使用
Redux核心概念
Redux Toolkit实践
▶
性能优化
memo使用
useCallback应用
代码分割实践
发布时间:
2025-03-22 12:39
↑
☰
# 组件组合模式 本文将详细介绍React组件的组合模式,帮助你理解如何构建可复用的组件系统。 ## 什么是组件组合? 组件组合是React中一种强大的代码复用模式,它允许你将多个组件组合在一起构建更复杂的UI。相比继承,组件组合提供了更灵活的方式来复用组件逻辑和UI结构。 主要优点: - 代码复用:避免重复编写相似的组件 - 关注点分离:每个组件专注于特定功能 - 灵活性:易于组合和定制组件 - 可维护性:组件之间松耦合,易于修改和测试 ## 基础组合模式 ### 1. 包含关系 ```jsx function Container({ children }) { return ( <div className="container"> {children} </div> ); } function App() { return ( <Container> <h1>Welcome</h1> <p>This is a container component</p> </Container> ); } ``` ### 2. 特殊子组件 ```jsx function Dialog({ title, children }) { return ( <div className="dialog"> <div className="dialog-title">{title}</div> <div className="dialog-content">{children}</div> </div> ); } function WelcomeDialog() { return ( <Dialog title="Welcome"> <h1>Welcome to our platform!</h1> <p>We're glad to have you here.</p> </Dialog> ); } ``` ## 高级组合模式 ### 1. 多插槽组合 ```jsx function Layout({ header, sidebar, content, footer }) { return ( <div className="layout"> <header className="header">{header}</header> <div className="main"> <aside className="sidebar">{sidebar}</aside> <main className="content">{content}</main> </div> <footer className="footer">{footer}</footer> </div> ); } function App() { return ( <Layout header={<Header />} sidebar={<Sidebar />} content={<MainContent />} footer={<Footer />} /> ); } ``` ### 2. 组件注入 ```jsx function DataTable({ data, rowComponent: Row }) { return ( <table> <tbody> {data.map(item => ( <Row key={item.id} {...item} /> ))} </tbody> </table> ); } function UserRow({ name, email }) { return ( <tr> <td>{name}</td> <td>{email}</td> </tr> ); } function App() { const users = [ { id: 1, name: 'John', email: 'john@example.com' }, { id: 2, name: 'Jane', email: 'jane@example.com' } ]; return <DataTable data={users} rowComponent={UserRow} />; } ``` ## 常用组合模式 ### 1. 容器模式 ```jsx function Card({ title, children, footer }) { return ( <div className="card"> {title && <div className="card-header">{title}</div>} <div className="card-body">{children}</div> {footer && <div className="card-footer">{footer}</div>} </div> ); } function UserCard({ user }) { return ( <Card title={<h2>{user.name}</h2>} footer={<button>View Profile</button>} > <p>{user.bio}</p> <div className="user-stats"> <span>Followers: {user.followers}</span> <span>Following: {user.following}</span> </div> </Card> ); } ``` ### 2. 高阶组件(HOC) ```jsx function withLoading(WrappedComponent) { return function WithLoadingComponent({ isLoading, ...props }) { if (isLoading) { return <LoadingSpinner />; } return <WrappedComponent {...props} />; }; } function UserList({ users }) { return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ); } const UserListWithLoading = withLoading(UserList); function App() { const [isLoading, setIsLoading] = useState(true); const [users, setUsers] = useState([]); return <UserListWithLoading isLoading={isLoading} users={users} />; } ``` ### 3. 渲染属性(Render Props) ```jsx function Mouse({ render }) { const [position, setPosition] = useState({ x: 0, y: 0 }); useEffect(() => { function handleMouseMove(event) { setPosition({ x: event.clientX, y: event.clientY }); } window.addEventListener('mousemove', handleMouseMove); return () => window.removeEventListener('mousemove', handleMouseMove); }, []); return render(position); } function App() { return ( <Mouse render={({ x, y }) => ( <div style={{ position: 'fixed', left: x, top: y }}> 🐭 </div> )} /> ); } ``` ## 最佳实践 ### 1. 组件接口设计 ```jsx // 保持接口简单且一致 function Button({ variant = 'primary', size = 'medium', children, onClick, ...props }) { return ( <button className={`btn btn-${variant} btn-${size}`} onClick={onClick} {...props} > {children} </button> ); } // 使用组件 function App() { return ( <div> <Button variant="primary" size="large" onClick={() => alert('Clicked!')}> Click me </Button> <Button variant="secondary" disabled> Disabled </Button> </div> ); } ``` ### 2. 组合优于继承 ```jsx // 不推荐使用继承 class SpecialButton extends Button { // ... } // 推荐使用组合 function SpecialButton(props) { return ( <Button {...props} className={`special-button ${props.className || ''}`} onClick={(e) => { // 特殊处理 if (props.onClick) { props.onClick(e); } }} /> ); } ``` ### 3. 关注点分离 ```jsx // 将逻辑和UI分离 function useUserData(userId) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchUser() { try { const data = await fetchUserById(userId); setUser(data); } finally { setLoading(false); } } fetchUser(); }, [userId]); return { user, loading }; } function UserProfile({ userId }) { const { user, loading } = useUserData(userId); if (loading) return <LoadingSpinner />; if (!user) return <ErrorMessage />; return ( <Card> <UserInfo user={user} /> <UserStats user={user} /> <UserActions user={user} /> </Card> ); } ``` ## 总结 本文详细介绍了React组件组合的核心概念和常用模式: 1. 基础组合方式(包含关系、特殊子组件) 2. 高级组合模式(多插槽、组件注入) 3. 常用设计模式(容器模式、HOC、渲染属性) 4. 最佳实践和设计原则 通过合理使用组件组合,可以构建出更加灵活、可维护的React应用。建议在实践中根据具体需求选择合适的组合模式,并始终遵循"组合优于继承"的原则。