当前位置: 首页 > article >正文

React底层常见的设计模式

在React中,常见的设计模式为开发者提供了结构化和可重用的解决方案,有助于提高代码的可维护性和可扩展性。以下是对React中几种常见设计模式的详细解析,并附上示例代码和注释:

1. 容器组件与展示组件模式(Container/Presentational Pattern)

描述
容器组件负责数据获取、状态管理和业务逻辑,而展示组件仅负责渲染UI,不直接管理状态。

示例代码

// 展示组件:TodoItem.js
import React from 'react';const TodoItem = ({ todo }) => (<div><span>{todo.text}</span><button onClick={() => alert(`Completed ${todo.text}`)}>Complete</button></div>
);export default TodoItem;// 容器组件:TodoList.js
import React, { Component } from 'react';
import TodoItem from './TodoItem';class TodoList extends Component {state = {todos: [{ id: 1, text: 'Learn React' },{ id: 2, text: 'Learn Redux' },],};render() {return (<div><h1>Todo List</h1><ul>{this.state.todos.map(todo => (<li key={todo.id}><TodoItem todo={todo} /></li>))}</ul></div>);}
}export default TodoList;

注释

  • TodoItem是一个展示组件,它接收一个todo对象作为props,并渲染出对应的文本和按钮。
  • TodoList是一个容器组件,它管理一个todos状态数组,并在渲染时遍历该数组,为每个todo项渲染一个TodoItem组件。

2. 高阶组件模式(Higher-Order Component Pattern, HOC)

描述
高阶组件是一个函数,它接收一个组件作为参数,并返回一个新的组件。这个新组件可以访问原始组件的props,并可以添加额外的props或行为。

示例代码

// 高阶组件:withLogging.js
import React from 'react';const withLogging = (WrappedComponent) => {return class extends React.Component {componentDidMount() {console.log(`${WrappedComponent.name} mounted`);}componentWillUnmount() {console.log(`${WrappedComponent.name} will unmount`);}render() {return <WrappedComponent {...this.props} />;}};
};// 使用高阶组件的组件:EnhancedTodoItem.js
import React from 'react';
import withLogging from './withLogging';
import TodoItem from './TodoItem'; // 假设TodoItem是上面定义的展示组件// 注意:这里我们实际上是在增强TodoItem组件,但为了示例清晰,我们假设有一个新的组件EnhancedTodoItem
const EnhancedTodoItem = withLogging(TodoItem);// 通常情况下,你会直接使用EnhancedTodoItem而不是TodoItem
// 但在这个例子中,我们只是为了展示HOC的用法,所以EnhancedTodoItem和TodoItem功能相同,只是多了日志记录。// 实际上,你可能会在EnhancedTodoItem中添加更多的逻辑或props。
export default EnhancedTodoItem;

注意:在上面的withLogging示例中,我们实际上没有直接对TodoItem进行增强(因为TodoItem已经是一个纯函数组件,并且没有额外的逻辑需要添加),但为了展示HOC的用法,我们假设有一个新的组件EnhancedTodoItem使用了这个HOC。在实际应用中,你会在HOC中添加额外的逻辑或props,并将其应用于需要增强的组件。

另外,由于TodoItem是一个函数组件,它没有name属性,所以console.log中的${WrappedComponent.name}可能不会显示你期望的名字。在实际应用中,你可能需要为函数组件添加一个displayName静态属性或使用其他方法来标识组件。

修正后的示例(为函数组件添加displayName):

// TodoItem.js(添加displayName)
import React from 'react';const TodoItem = ({ todo }) => (// ...之前的代码
);TodoItem.displayName = 'TodoItem'; // 添加displayName以便在日志中正确显示组件名export default TodoItem;

这样,当使用withLogging高阶组件时,日志中就会正确地显示TodoItem mountedTodoItem will unmount

当然,除了之前提到的容器组件与展示组件模式和高阶组件模式外,React中还有其他常见的设计模式。以下是对这些模式的详细解析,并附上示例代码和注释:

3. 渲染属性模式(Render Props Pattern)

描述
渲染属性模式是一种将函数作为属性传递给组件的技术,该函数返回一个React元素。这种模式允许组件之间共享代码和逻辑。

示例代码

// MouseTracker.js
import React, { useState } from 'react';const MouseTracker = ({ render }) => {const [position, setPosition] = useState({ x: 0, y: 0 });const handleMouseMove = (event) => {setPosition({ x: event.clientX, y: event.clientY });};return (<div style={{ height: '100vh' }} onMouseMove={handleMouseMove}>{render(position)}</div>);
};export default MouseTracker;// App.js
import React from 'react';
import MouseTracker from './MouseTracker';const App = () => (<MouseTrackerrender={({ x, y }) => (<h1>鼠标的当前位置是 ({x}, {y})</h1>)}/>
);export default App;

注释

  • MouseTracker组件接收一个render属性,该属性是一个函数,它接收鼠标位置作为参数,并返回一个React元素。
  • App组件中,我们使用MouseTracker组件,并传递一个函数作为render属性,该函数根据鼠标位置渲染一个h1元素。

4. 自定义钩子模式(Custom Hook Pattern)

描述
自定义钩子允许你将组件逻辑提取到可重用的函数中。它们可以让你在不增加组件类的情况下复用状态逻辑。

示例代码

// useFetch.js
import { useState, useEffect } from 'react';const useFetch = (url) => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {fetch(url).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(jsonData => {setData(jsonData);setLoading(false);}).catch(error => {setError(error);setLoading(false);});}, [url]);return { data, loading, error };
};export default useFetch;// DataDisplay.js
import React from 'react';
import useFetch from './useFetch';const DataDisplay = ({ url }) => {const { data, loading, error } = useFetch(url);if (loading) return <p>Loading...</p>;if (error) return <p>Error: {error.message}</p>;return (<pre>{JSON.stringify(data, null, 2)}</pre>);
};export default DataDisplay;

注释

  • useFetch是一个自定义钩子,它接收一个URL作为参数,并返回一个包含数据、加载状态和错误信息的对象。
  • DataDisplay组件使用useFetch钩子来获取数据,并根据加载状态和错误信息渲染相应的UI。

5. 组合模式(Composite Pattern)

描述
组合模式允许你将对象组合成树形结构以表示“部分-整体”的层次结构。在React中,这通常体现在组件树的设计上。

示例代码(简化版):

// Accordion.js
import React, { useState } from 'react';const Accordion = ({ children }) => {const [activeIndex, setActiveIndex] = useState(null);const handleItemClick = (index) => {setActiveIndex(index);};return (<div>{React.Children.map(children, (child, index) =>React.cloneElement(child, {isActive: index === activeIndex,onItemClick: () => handleItemClick(index),}))}</div>);
};// AccordionItem.js
import React from 'react';const AccordionItem = ({ title, children, isActive, onItemClick }) => (<div><h2 onClick={onItemClick}>{title}</h2>{isActive && <div>{children}</div>}</div>
);export { Accordion, AccordionItem };// App.js
import React from 'react';
import { Accordion, AccordionItem } from './Accordion';const App = () => (<Accordion><AccordionItem title="Item 1">Content 1</AccordionItem><AccordionItem title="Item 2">Content 2</AccordionItem><AccordionItem title="Item 3">Content 3</AccordionItem></Accordion>
);export default App;

注释

  • Accordion组件接收子组件(AccordionItem组件)作为参数,并管理哪个项目处于活动状态。
  • AccordionItem组件接收标题、子组件、活动状态和点击事件处理器作为props,并根据活动状态渲染内容。
  • App组件中,我们使用Accordion组件,并传递多个AccordionItem组件作为其子组件。

这些设计模式在React开发中非常常见,它们有助于提高代码的可维护性、可扩展性和重用性。

相关文章:

React底层常见的设计模式

在React中&#xff0c;常见的设计模式为开发者提供了结构化和可重用的解决方案&#xff0c;有助于提高代码的可维护性和可扩展性。以下是对React中几种常见设计模式的详细解析&#xff0c;并附上示例代码和注释&#xff1a; 1. 容器组件与展示组件模式&#xff08;Container/P…...

机器视觉--线扫相机触发

绪论 在当今蓬勃发展的机器视觉领域&#xff0c;线扫相机堪称关键角色&#xff0c;它凭借高分辨率的扫描成像能力&#xff0c;广泛应用于工业检测、物流识别、印刷质量检测等众多核心场景。线扫相机的触发方式作为成像环节的核心要素&#xff0c;直接决定了图像采集的精准度与…...

Flutter的permission_handler插件检查iOS的通知权限不准确

今天&#xff0c;做好了一个功能&#xff0c;就是在app内检查用户有没有给当前APP打开通知权限&#xff0c; 如果没打开&#xff0c;就展示一个 banner &#xff0c;让用户去点击banner去打开权限 。 android上测试得非常顺利&#xff0c; 结果&#xff0c; 在iOS 上就是不…...

五、数据库索引详解:作用、原理与使用指南

数据库索引详解&#xff1a;作用、原理与使用指南 一、索引的作用&#xff08;为什么需要索引&#xff1f;&#xff09; 1. 生活中的类比 想象你要在一本 500 页的书中快速找到「数据库索引」相关内容&#xff1a; 没有目录&#xff1a;需要逐页翻找 → 全表扫描有目录&…...

vue使用a-table设置自定义合并字段实现某字段值相同则合并行

背景&#xff1a; 笔者前端使用ant-design-vue,二次开发了a-table,但a-table组件的属性方法都可以用&#xff1b; 业务需求&#xff1a;物资存放在不同的仓库&#xff0c;显示物资统计表格&#xff0c;以物资分组合并显示物资名称、总数量&#xff08;物资A在所有库房总数量&a…...

Docker容器日常维护常用命令大全

友情提示&#xff1a;本文内容由银河易创&#xff08;https://ai.eaigx.com&#xff09;AI创作平台deepseek-v3模型生成&#xff0c;文中所有命令未进行验证&#xff0c;仅供参考。请根据具体情况和需求进行适当的调整和验证。 引言 Docker作为当前最流行的容器化技术&#xf…...

《昇腾推理服务器+DeepSeek大模型》技术培训在图为科技成功举办

2月17日&#xff0c;华为政企业务团队受邀莅临图为科技深圳总部&#xff0c;并成功举办了一场聚焦于《昇腾推理服务器DeepSeek大模型》的专业知识培训。 此次培训活动不仅深化了双方的技术交流&#xff0c;更标志着昇腾AI与DeepSeek大模型的全面融合应用即将迈入实质性落地的新…...

【Java环境】配置极简描述

241220 241220 241220 Java环境配置 下载JDK 注意&#xff1a;最好下载 Long-Term SupportLTS&#xff0c;长期支持版本【目前是JDK21】 下载地址&#xff1a;Java Downloads | Oracle. 下载这个&#xff1a;x64 Installer 。 安装时&#xff0c;路径可改&#xff0c;其余无…...

DeepSeek开源周Day5: 3FS存储系统与AI数据处理新标杆

项目地址&#xff1a; GitHub - deepseek-ai/3FS: A high-performance distributed file system designed to address the challenges of AI training and inference workloads.GitHub - deepseek-ai/smallpond: A lightweight data processing framework built on DuckDB and…...

FastAPI系列:如何配置跨域访问(CORS)

默认情况下&#xff0c;FastAPI应用程序不允许来自不同来源的请求。当你有一个前端应用程序与后端API通信&#xff0c;并且它们托管在不同的域或端口上时&#xff0c;在FastAPI中允许来自不同来源的请求是一种常见的场景。这被称为CORS&#xff08;跨域资源共享&#xff09;&am…...

Flutter 学习之旅 之 flutter 在 Android 端进行简单的打开前后相机预览 / 拍照保存

Flutter 学习之旅 之 flutter 在 Android 端进行简单的打开前后相机预览 / 拍照保存 目录 Flutter 学习之旅 之 flutter 在 Android 端进行简单的打开前后相机预览 / 拍照保存 一、简单介绍 二、简单介绍 camera 三、安装 camera 四、简单案例实现 五、关键代码 一、简单…...

【deepseek第一课】从0到1介绍 采用ollama安装deepseek私有化部署,并实现页面可视化

【deepseek第一课】从0到1介绍 采用ollama安装deepseek私有化部署,并实现页面可视化 1. ollama安装1.1 linux安装1.2 windows安装2. deepSeek支持的7种蒸馏模型2.1 蒸馏模型介绍2.2 7种模型特点2.3 安装deepseek-r1:14b模型3. openwebui图形化页面安装4. java连接大模型的三…...

【Vue3 Teleport 技术解析:破解弹窗吸附与滚动列表的布局困局】

&#x1f31f; Vue3 Teleport 技术解析&#xff1a;破解弹窗吸附与滚动列表的布局困局 &#x1f30d; 背景&#xff1a;传统组件嵌套的布局之痛 在传统前端开发中&#xff0c;组件往往被严格限制在父级 DOM 结构中&#xff0c;这导致三大典型问题&#xff1a; 层级监禁 &…...

鸿蒙HarmonyOS 开发简介

鸿蒙开发入门教程 一、技术简介 鸿蒙操作系统&#xff08;HarmonyOS&#xff09;是面向万物互联时代的全场景分布式操作系统&#xff0c;具备分布式软总线、分布式数据管理、分布式任务调度等核心能力&#xff0c;能让设备间实现无缝连接与协同&#xff0c;为用户提供统一、流…...

VBA技术资料MF276:在集合中使用键

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…...

谈谈 Node.js 中的文件系统(fs)模块,如何进行文件读写操作?

Node.js 文件系统&#xff08;fs&#xff09;模块深度解析与实践指南 一、模块基础与核心能力 Node.js 的 fs 模块提供了完整的文件系统操作能力&#xff0c;涵盖 50 个方法&#xff0c;主要分为以下类型&#xff1a; 文件读写&#xff1a;基础 CRUD 操作目录操作&#xff1…...

Python Cookbook-2.18 从指定的搜索路径寻找文件

任务 给定一个搜索路径(一个描述目录信息的字符串)&#xff0c;需要根据这个路径和请求的文件名找到第一个符合要求的文件。 解决方案 需要循环指定的搜索路径中的目录: import os def search_file(filename,search path&#xff0c;pathsepos.pathsep): """…...

安装Git(小白也会装)

一、官网下载&#xff1a;Git 1.依次点击&#xff08;红框&#xff09; 不要安装在C盘了&#xff0c;要炸了&#xff01;&#xff01;&#xff01; 后面都 使用默认就好了&#xff0c;不用改&#xff0c;直接Next&#xff01; 直到这里&#xff0c;选第一个 这两种选项的区别如…...

工学一体化教育模式的核心内涵及实践意义探究

工学一体化是一种将理论教学与实践操作深度融合的教育模式&#xff0c;旨在通过工作过程与学习过程的有机结合&#xff0c;培养具备综合职业能力和创新能力的技能人才。 一、工学一体化的核心内涵 工学一体化教学模式强调“在工作中学习、在学习中工作”&#xff0c;其核心在于…...

前端正则表达式完全指南:从入门到实战

文章目录 第一章&#xff1a;正则表达式基础概念1.1 什么是正则表达式1.2 正则表达式工作原理1.3 基础示例演示 第二章&#xff1a;正则表达式核心语法2.1 元字符大全表2.2 量词系统详解2.3 字符集合与排除 第三章&#xff1a;前端常用正则模式3.1 表单验证类3.1.1 邮箱验证3.1…...

Chromium项目相关

Chromium项目相关 Chromium 是一个开源浏览器项目&#xff0c;旨在为所有用户构建一种更安全、更快速、更稳定的方式来体验 Web。 自 Google 在 2008 年宣布 Chromium 项目以来&#xff0c;他们一直很高兴能够在开源 Web 浏览器的良好基础上进行构建&#xff0c;并为富 Web 平…...

自动驾驶测试场景相关概念

自动驾驶测试场景 一、概念二、分类2.1、按照场景的抽象程度可分为&#xff1a;功能场景、逻辑场景、具体场景。2.2.、​按功能划分2.3、 ​按环境复杂度2.3、按场景类型 三、要素四、挑战与趋势4.1、长尾场景覆盖​4.2、伦理决策测试​4.3、车路协同测试​4.4、联邦学习驱动​…...

给小白的oracle优化工具,了解一下

有时懒得分析或语句太长&#xff0c;可以尝试用oracle的dbms_sqldiag包进行sql优化&#xff0c; --How To Use DBMS_SQLDIAG To Diagnose Query Performance Issues (Doc ID 1386802.1) --诊断SQL 性能 SET ECHO ON SET LINESIZE 132 SET PAGESIZE 999 SET LONG 999999 SET SER…...

DMA发送全部历史记录数据到串口

背景 博主参与的项目中&#xff0c;有个读取全部历史记录的功能&#xff0c;如果下位机在主程序中将全部历史记录单纯地通过串口传输会比较占用cpu资源&#xff0c;影响主程序中别的功能。最后商量得出以下实现方案&#xff1a; 定义两个发送缓冲区DMATxbuf1和DMATxbuf2&…...

基因型—环境两向表数据分析——品种生态区划分

参考资料&#xff1a;农作物品种试验数据管理与分析 用于品种生态区划分的GGE双标图有两种功能图&#xff1a;试点向量功能图和“谁赢在哪里”功能图。双标图的具体模型基于SD定标和h加权和试点中心化的数据。本例中籽粒产量的GGE双标图仅解释了G和GE总变异的53.6%&#xff0c;…...

电路中如何计算电容容值大小

一个例题&#xff1a; 【电路中电容容值是怎么算出来的&#xff1f;】https://www.bilibili.com/video/BV1RQ4y1c7i1?vd_source3cc3c07b09206097d0d8b0aefdf07958...

c++中迭代器和指针有什么区别?

在 C 中&#xff0c;迭代器和指针虽然在某些场景下有相似的行为&#xff0c;但它们在设计目的、功能和使用场景上有本质区别。以下是详细对比和最佳实践&#xff1a; 一、核心区别对比表 特征指针迭代器本质原生数据类型&#xff0c;直接存储内存地址类对象&#xff0c;抽象容…...

GPT大语言模型与搜索引擎:技术本质与应用场景的深度解析

引言 在人工智能和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;GPT&#xff08;Generative Pre-trained Transformer&#xff09;大语言模型和搜索引擎是两个备受关注的技术。尽管它们都涉及到信息检索和生成&#xff0c;但它们在技术原理、应用场景和用户体验上…...

FreeRTOS-中断管理

实验目的 创建一个队列及一个任务&#xff0c;按下按键 KEY1 触发中断&#xff0c;在中断服务函数里向队列里发送数据&#xff0c;任务则阻塞接 收队列数据。 实验代码 实验结果 这样就实现了&#xff0c;使用中断往队列的发送信息&#xff0c;用任务阻塞接收信息...

计算机毕业设计SpringBoot+Vue.js音乐网站(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...