首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 课程介绍
02 | React出现的历史背景及特性介绍
03 | 以组件方式考虑UI的构建
04 | JSX的本质 : 不是模板引擎,而是语法糖
05 | React组件的生命周期及其使用场景
06 | 理解Virtual DOM及key属性的作用
07 | 组件设计模式 : 高阶组件和函数作为子组件
08 | 理解新的Context API及其使用场景
09 | 使用脚手架工具创建React项目
10 | 打包和部署
11 | Redux(1) : 前端为何需要状态管理库
12 | Redux(2) : 深入理解Store、Action、Reducer
13 | Redux(3) : 在React中使用Redux
14 | Redux(4) : 理解异步Action、Redux中间件
15 | Redux(5) : 如何组织Action和Reducer
16 | Redux(6) : 理解不可变数据(Immutability)
17 | React Router(1):路由不只是页面切换,更是代码组织方式
18 | React Router(2):参数定义,嵌套路由的使用场景
19 | UI组件库对比和介绍:Ant.Design、Material UI、Semantic UI
20 | 使用Next.js创建React同构应用
21 | 使用Jest、Enzyme等工具进行单元测试
22 | 常用开发调试工具:ESLint、Prettier、React DevTool、Redux DevTool
23 | 前端项目的理想架构:可维护、可扩展、可测试、易开发、易建构
24 | 拆分复杂度(1):按领域模型(feature)组织代码,降低耦合度
25 | 拆分复杂度(2):如何组织component、action和reducer
26 | 拆分复杂度(3):如何组织React Router的路由配置
27 | 使用Rekit(1):创建项目,代码生成和重构
28 | 使用Rekit(2):遵循最佳实践,保持代码一致性
29 | 使用React Router管理登录和授权
30 | 实现表单(1):初始数据,提交和跳转
31 | 实现表单(2):错误处理,动态表单元素,内容动态加载
32 | 列表页(1):搜索,数据缓存和分页
33 | 列表页(2):缓存更新,加载状态,错误处理
34 | 页面数据需要来源多个请求的处理
35 | 内容页的加载与缓存
36 | 基于React Router实现分步操作
37 | 常见页面布局的实现
38 | 使用React Portals实现对话框,使用antd对话框
39 | 集成第三方JS库:以d3.js为例
40 | 基于路由实现菜单导航
41 | React中拖放的实现
42 | 性能永远是第一需求:时刻考虑性能问题
43 | 网络性能优化:自动化按需加载
44 | 使用Reselect避免重复计算
45 | 下一代React:异步渲染
46 | 使用Chrome DevTool进行性能调优&结课测试
当前位置:
首页>>
技术小册>>
深入学习React实战进阶
小册名称:深入学习React实战进阶
### 07 | 组件设计模式:高阶组件和函数作为子组件 在React的广阔生态系统中,组件设计模式是构建可维护、可扩展和可复用应用的关键。其中,高阶组件(Higher-Order Components, HOCs)与将函数作为子组件(Render Props或函数式子组件)是两种极其强大且灵活的设计模式,它们为开发者提供了强大的抽象能力,使得组件间的逻辑复用与解耦变得简单高效。本章将深入探讨这两种模式的概念、应用场景、实现方式以及它们之间的比较。 #### 一、高阶组件(HOCs) ##### 1.1 定义与概念 高阶组件是一个函数,这个函数接受一个组件并返回一个新的组件。这个新组件可以拥有增强的功能,比如新的props、状态管理、生命周期方法等,而无需修改原始组件的代码。HOC不是React API的一部分,而是一种基于React的组合特性而形成的模式。 ##### 1.2 使用场景 - **代码复用、逻辑抽象**:当多个组件共享相同的行为或状态时,可以使用HOC来封装这些逻辑。 - **访问操作DOM、状态管理集成**:如集成Redux、MobX等状态管理库,或在组件中直接操作DOM。 - **条件渲染、性能优化**:如通过HOC实现懒加载、代码分割或基于特定条件渲染组件。 ##### 1.3 实现方式 ```jsx function withLogging(WrappedComponent) { return class extends React.Component { componentDidMount() { console.log(`Component ${WrappedComponent.displayName || WrappedComponent.name} mounted`); } componentWillUnmount() { console.log(`Component ${WrappedComponent.displayName || WrappedComponent.name} will unmount`); } render() { return <WrappedComponent {...this.props} />; } }; } // 使用HOC const LoggedUser = withLogging(UserProfile); ``` 在上面的例子中,`withLogging`是一个高阶组件,它接受一个组件`WrappedComponent`并返回一个新的组件,这个新组件在挂载和卸载时会打印日志。 ##### 1.4 注意事项 - **不要修改传入的组件**:HOC应透明地传递props,并且不要修改传入的组件实例。 - **静态方法必须手动复制**:如果HOC需要返回的组件保留原始组件的静态方法,则需要手动复制。 - **Refs不会自动传递**:如果HOC需要转发refs,应使用React.forwardRef API。 #### 二、函数作为子组件(Render Props) ##### 2.1 定义与概念 函数作为子组件,也称为Render Props,是一种将组件逻辑通过props中的函数传递给子组件的模式。这种模式允许子组件通过调用这个传入的函数来渲染自身,从而实现高度的灵活性和复用性。 ##### 2.2 使用场景 - **状态下沉**:当多个子组件需要根据同一个状态进行渲染时,可以将状态管理逻辑放在父组件,并通过Render Props将渲染逻辑传递给子组件。 - **自定义渲染逻辑**:当组件需要根据不同条件渲染不同UI时,Render Props提供了一种灵活的方式来定义这些渲染逻辑。 - **高阶组件的替代**:在某些情况下,Render Props可以作为一种更轻量级的替代方案,特别是当不需要对组件进行包装或修改时。 ##### 2.3 实现方式 ```jsx function MouseTracker({ render }) { return ( <div> <p>Move the mouse around!</p> {render(position)} </div> ); } function App() { let [position, setPosition] = React.useState({ x: 0, y: 0 }); const handleMouseMove = (event) => { setPosition({ x: event.clientX, y: event.clientY }); }; return ( <div onMouseMove={handleMouseMove}> <MouseTracker render={({ x, y }) => ( <p>The mouse position is ({x}, {y})</p> )} /> </div> ); } ``` 在这个例子中,`MouseTracker`组件接受一个`render`函数作为props,这个函数根据鼠标的位置进行渲染。 ##### 2.4 注意事项 - **避免在render方法中创建新的函数**:这可能会导致不必要的组件重渲染。应该尽量在组件外部定义这些函数或使用`useCallback`钩子。 - **清晰的API设计**:Render Props的API应该清晰明了,避免传入过多的参数或复杂的逻辑,以免影响组件的易用性。 #### 三、高阶组件 vs 函数作为子组件 ##### 3.1 优点对比 - **高阶组件**: - 封装性强,可以修改或增强组件的props、状态或生命周期。 - 易于理解和实现,特别是对于初学者来说。 - **函数作为子组件**: - 更加灵活,可以根据不同的props或状态动态地渲染不同的子组件。 - 避免了不必要的组件包装,可能有助于性能优化。 ##### 3.2 缺点对比 - **高阶组件**: - 可能导致组件树过于复杂,特别是当多个HOC嵌套使用时。 - 静态方法需要手动复制,可能导致维护成本增加。 - **函数作为子组件**: - 可能会导致组件的props列表过长或复杂,影响组件的清晰度。 - 对于某些情况,可能不如HOC直观或易于理解。 ##### 3.3 选择原则 - 当需要增强或修改组件的行为(如添加新的props、状态或生命周期方法)时,倾向于使用高阶组件。 - 当需要根据不同条件或状态动态渲染不同的子组件时,或者当需要更高的灵活性时,倾向于使用函数作为子组件。 总之,高阶组件和函数作为子组件都是React中强大的设计模式,它们各有优缺点,适用于不同的场景。在实际开发中,应根据具体需求和团队习惯来选择合适的模式。通过合理运用这些设计模式,可以显著提升React应用的代码质量和开发效率。
上一篇:
06 | 理解Virtual DOM及key属性的作用
下一篇:
08 | 理解新的Context API及其使用场景
该分类下的相关小册推荐:
React全家桶--前端开发与实例(下)
React 进阶实践指南
剑指Reactjs
ReactJS面试指南
React全家桶--前端开发与实例(上)