焦点精选!组件结构 - 在React中构建可重用和可维护的组件
我们将探讨组件结构的重要性以及它如何有助于创建高度可重用、模块化且易于维护的组件。
在 React 中构建可重用和可维护的组件不仅仅是编写代码;还需要编写代码。它涉及采用最佳实践并遵循合理的架构原则。
通过仔细构建我们的组件,遵守单一职责原则,并采用原子设计和组件组合等概念,我们可以创建更加模块化、更易于测试和更易于维护的代码。
(资料图)
这种方法可以实现更高效的开发过程,并最终产生高质量、可扩展的 React 应用程序。
(更|多优质内|容:java567 点 c0m)
让我们考虑一个在 React 中实现的 Todo 应用程序的示例。
// ❌ Bad code with multiple responsibilities import React, { useState } from 'react'; const TodoApp = () => { // Handling state ❌ const [todos, setTodos] = useState([]); const [newTodo, setNewTodo] = useState(''); // Handle input change ❌ const handleInputChange = (e) => { setNewTodo(); }; // Handle todo logic ❌ const handleAddTodo = () => { if (() !== '') { const updatedTodos = [...todos, newTodo]; setTodos(updatedTodos); setNewTodo(''); } }; const handleDeleteTodo = (index) => { const updatedTodos = ((_, i) => i !== index); setTodos(updatedTodos); }; const handleCompleteTodo = (index) => { const updatedTodos = ((todo, i) => { if (i === index) { return { ...todo, completed: ! }; } return todo; }); setTodos(updatedTodos); }; // ❌ It doesn't provide a clear separation of smaller reusable components. return ( <div> <h1>Todo App</h1> <input type="text" value={newTodo} onChange={handleInputChange} /> <button onClick={handleAddTodo}>Add Todo</button> <ul> {((todo, index) => ( <li key={index}> <span style={{ textDecoration: ? 'line-through' : 'none' }}>{}</span> <button onClick={() => handleDeleteTodo(index)}>Delete</button> <button onClick={() => handleCompleteTodo(index)}> { ? 'Mark Incomplete' : 'Mark Complete'} </button> </li> ))} </ul> </div> ); };
上面的代码库包含一个组件,它处理从呈现 UI到处理数据和状态管理的所有事务。这种单一的方法导致缺乏关注点分离,并且违反了SRP和原子设计原则。
为了改进代码,我们可以遵循SRP和原子设计原则:
单一职责原则(SRP)
该原则指出,类或组件应该有单一的职责或单一的更改原因。通过使组件专注于特定任务,您可以提高代码的可读性、可维护性和可重用性。
它促进将复杂的功能分解为更小、更集中的部分,更容易理解、测试和维护。
它鼓励组件有明确和具体的职责,增强其可重用性和可维护性。
它通过让组件专注于特定任务来帮助避免紧密耦合的组件。
让我们分解一下整体,
TodoInput:将输入处理逻辑提取到单独的useTodoInput自定义挂钩和组件中TodoInput。
负责处理用户输入并添加新的待办事项。
TodoList:将待办事项列表处理逻辑提取到单独的useTodoList自定义挂钩和组件中TodoList。
负责呈现待办事项列表。
TodoItem:将各个待办事项的渲染逻辑移至单独的TodoItem组件中。
负责渲染单个待办事项。
通过将状态和事件处理逻辑分离到自定义挂钩或组件中,我们确保每个组件都有以下单一职责。
待办事项输入
useTodoInput自定义挂钩可以使用 useState 挂钩管理输入状态并处理输入更改事件
使用
// ✅ Responsible for manage state and UI events import { useState } from "react"; const useTodoInput = (onAddTodo) => { const [inputValue, setInputValue] = useState(""); const [disabled, setDisabled] = useState(true); const handleSubmit = (e) => { (); onAddTodo(inputValue); clearInput(); }; const handleInputChange = (e) => { const value = ; setInputValue(value); setDisabled(() === ""); }; const clearInput = () => { setInputValue(""); setDisabled(true); }; return { disabled, inputValue, handleInputChange, handleSubmit }; }; export { useTodoInput };
通过使用自定义钩子,我们可以以可重用和模块化的方式封装状态和事件处理逻辑,从而提高代码的可重用性和可维护性。
将与输入字段、“添加待办事项”按钮和待办事项列表相关的 JSX 代码移至单独的 JSX 文件中。
// // ✅ Responsible for rendering TodoInput UI const TodoInput = ({ onAddTodo }) => { const { disabled, inputValue, handleInputChange, handleSubmit } = useTodoInput(onAddTodo); return ( <form className="todo-input" onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={handleInputChange} placeholder="Add a todo" /> <button className={`add-button ${disabled ? "disabled" : ""}`} disabled={disabled} type="submit" > Add </button> </form> ); };
通过将 JSX 代码分成单独的文件,我们可以提高代码的组织性和可读性,从而更容易维护和理解组件结构。
像这样我们需要拆分TodoItem和TodoList。
这种重构方法通过为每个组件分配单一职责来遵守 SRP,利用自定义挂钩进行状态和事件处理,并将 JSX 代码分离为可重用的组件,从而提高 React 应用程序的模块化性和可维护性。
最后,组件结构如下所示,
// ✅ Component Stucture components/ ├── todo-input/ │ ├── │ ├── │ └── ├── todo-item/ │ ├── │ └── ├── todo-list/ │ ├── │ ├── │ └── └── ...
您可以在codesandbox 中查看整个代码库。
我们可以使用原子设计原则进一步重构这个代码库。
原子设计原理
原子设计是一种根据组件的抽象级别和复杂性以分层方式设计和组织组件的方法。
它将组件分为五个级别:原子、分子、有机体、模板和页面,每个级别都有特定的职责。
原子:在最低级别,原子代表最小和最基本的 UI 元素,例如按钮、输入或图标。
他们有单一的职责,专注于其视觉外观和基本功能。
分子:分子是原子的组合,它们共同作用以创建更复杂的 UI 元素。
它们的责任级别稍高,代表一组相关的原子。
有机体:有机体由分子和原子组成,代表用户界面更大、更独立的部分。
它们具有更复杂的行为,可能包括状态管理和交互逻辑。
模板:模板是有机体的特定排列,为页面或部分提供基本结构。
它们定义了 UI 的整体布局和组成。
页面:页面是用真实数据填充模板的实例,创建供用户交互的实际内容。
让我们以同一个待办事项应用程序为例。我将使用原子设计模式给出高级代码设计:
原子
Atoms 包含小型、可重用的 UI 组件,例如Button和Input。
// ✅ Atoms // const Button = ({ onClick, children }) => { return ( <button className="button" onClick={onClick}> {children} </button> ); }; // const Input = ({ value, onChange }) => { return ( <input className="input" type="text" value={value} onChange={onChange} /> ); };
每个原子都有自己的 JavaScript 文件 ( , ) 和 CSS 文件 ( , )。
分子
分子目录包含形成更复杂组件的原子组合 (),例如 TodoItem组件。
// ✅ Molecules // const TodoItem = ({ todo, onDelete, onComplete }) => { return ( <li className="todo-item"> <span className={ ? 'completed' : ''}>{}</span> <Button onClick={onDelete}>Delete</button> <Button onClick={onComplete}> { ? 'Mark Incomplete' : 'Mark Complete'} </Button> </li> ); };
它有自己的 JavaScript 文件 ( ) 和 CSS 文件 ( )。
生物体
有机体目录包含更大、功能更丰富的组件,例如TodoForm和TodoList组件。
// ✅ Organisms // const TodoForm = ({ onAddTodo }) => { const {inputChange, addTodo} = useTodoForm(); return ( <div className="todo-form"> <Input value={newTodo} onChange={inputChange} /> <Button onClick={addTodo}>Add Todo</Button> </div> ); }; // const TodoList = ({ todos, onDeleteTodo, onCompleteTodo }) => { return ( <ul className="todo-list"> {((todo, index) => ( <TodoItem key={index} todo={todo} onDelete={() => onDeleteTodo(index)} onComplete={() => onCompleteTodo(index)} /> ))} </ul> ); };
它们由分子和/或原子组成,并有自己的 JSX(、)、自定义 Hooks()和CSS文件。
模板
模板包含提供页面或布局整体结构的组件。在这种情况下,Todo模板负责呈现TodoForm和TodoList组件。
// ✅ Templates // const Todo = () => { const { todos, addTodo, deleteTodo, completeTodo } = useTodo(); return ( <div className="todo-app"> <h1>Todo App</h1> <TodoForm onAddTodo={addTodo} /> <TodoList todos={todos} onDeleteTodo={deleteTodo} onCompleteTodo={completeTodo} /> </div> ); };
它有自己的 JSX 文件 ( ) 和自定义 Hook ( ) 以及 CSS 文件 ( )。
页数
代表应用程序中特定页面的页面目录组件。在此示例中,有一个HomePage组件充当 Todo 应用程序的主入口点。
// ✅ Pages // const HomePage = () => { return ( <div className="home-page"> <TodoApp /> </div> ); };
此示例演示了如何使用原子设计模式构建 Todo 应用程序代码库。每个组件负责一个关注点,并且可以轻松地重用和组合它们以构建完整的 Todo 应用程序。
最后的想法
设计 React 应用程序时,必须避免将多个职责分配给单个组件。以下是一些实用策略,可帮助您实现更清晰、更易于维护的代码库:
1. 明确职责:明确定义每个组件的目的。将复杂的功能分解为更小、更集中的组件,并具有明确的职责。
2. 关注点分离:根据应用程序的功能将应用程序划分为不同的组件来分离关注点。每个组件都应该具有特定的角色并处理单一的职责。
3. 组件组合:不要构建处理多个任务的大型组件,而是通过组合较小的、可重用的组件来组合您的 UI。这促进了可重用性和模块化。
4. 单任务功能:将复杂的逻辑从组件中提取到单独的功能或实用模块中。通过将特定功能封装在单独的函数中,您可以使组件专注于渲染和 UI 相关任务。
5. 遵循 SOLID 原则:遵守 SOLID 原则,例如单一职责原则 (SRP),该原则规定组件应该只有一个更改理由。这一原则可帮助您设计专注、可维护且更易于测试的组件。
6. 使用自定义钩子:将通用逻辑提取到可以跨组件共享的自定义钩子中。这允许您重用逻辑,而不会给各个组件带来不必要的复杂性。
7. 模块化架构:使用模块化架构组织代码库,例如基于功能的文件夹结构。这种方法促进了关注点的分离,并有助于使组件专注于其特定的职责。
通过有意识地根据这些实践来设计 React 应用程序,您可以避免向组件分配多重职责。这会带来更干净、更易于维护的代码,更容易理解、测试和扩展。
奖励 - 组件层次结构
通常建议遵循特定的组件层次结构,以保持代码库的一致性和可读性。
// ✅ Component Hierarchy // External dependencies import React, { useState, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; // Internal dependencies import { TodoItem } from './TodoItem'; import { TodoUtils } from '../utils'; import { useTodo } from '../hooks'; import { withTimer } from '../hoc'; import { TodoType } from '../enums'; // Stylesheets import './'; import '../styles/'; // Assets import todoImage from '../assets/'; const Todo = () => { // State logic const [todos, setTodos] = useState([]); // Ref const inputRef = useRef(null); // Variable const title = 'Todo List'; // Custom hook const {addTodo} = useTodo(); // Higher-order component const timer = withTimer(TodoItem); // Component lifecycle methods (useEffect) useEffect(() => { //... }, []); // Component render return ( <div> {/* Component JSX */} </div> ); } = { // Prop types declaration }; export { Todo };
通过以一致且有组织的方式构建组件层次结构,您可以提高 React 应用程序的可读性、可维护性和可扩展性。
定义良好的层次结构可帮助开发人员浏览代码库、理解组件关系并高效地进行修改。
请继续关注我未来的博客文章中有关构建高质量 React 应用程序的更多提示和技巧!
快乐编码!
(更|多优质内|容:java567 点 c0m)
标签:
-
2022-09-15 14:23:06
杨莉娜租借加盟巴黎圣日耳曼 与姆巴佩梅西拉莫斯一起共事<
北京时间9月13日下午,法甲女足俱乐部巴黎圣日耳曼正式官宣中国女足国脚杨莉娜完成租借加盟,合同期至2023年6月。杨莉娜成为目前国家队中第
-
2022-02-07 14:57:45
奇迹!绝杀!女足亚洲杯逆转夺冠!<
刚刚,中国女足上演逆转绝杀奇迹!她们在亚洲杯决赛中3:2力克韩国队,时隔16年再夺亚洲杯冠军!
-
2022-02-07 14:57:45
中国政府与阿根廷共和国政府签署共建“一带一路”谅解备忘录<
新华社北京2月6日电(记者安蓓)国家发展改革委6日称,国家发展改革委主任何立峰与阿根廷外交、国际贸易和宗教事
-
2022-02-07 14:57:43
中华人民共和国和阿根廷共和国关于深化中阿全面战略伙伴关系的联合声明(全文)<
新华社北京2月6日电中华人民共和国和阿根廷共和国关于深化中阿全面战略伙伴关系的联合声明一、应中方邀请,阿根廷
-
2022-02-07 14:57:40
春节假期国内旅游出游2.51亿人次<
春节遇冬奥,旅游年味浓。根据文化和旅游部数据中心测算,2022年春节假期7天,全国国内旅游出游2 51亿人次,同比
-
2023-06-27 06:23:39
焦点精选!组件结构 - 在React中构建可重用和可维护的组件
我们将探讨组件结构的重要性以及它如何有助于创建高度可重用、模块化且
-
2023-06-27 05:42:14
特百佳动力科技股份有限公司加快产品开发—— 发力新能源重卡赛道
走进特百佳动力科技股份有限公司(以下简称“特百佳”)的生产车间,工
-
2023-06-27 03:04:07
定阳县(关于定阳县介绍) 环球快消息
大家好,小万来为大家解答以上的问题。定阳县,关于定阳县介绍这个很多
-
2023-06-27 00:55:30
【速看料】长沙代驾怎么收费标准 长沙代驾怎么收费的
2、长沙代驾怎么收费的。3、长沙代驾起步价多少钱。4、长沙什么代驾便
-
2023-06-26 23:03:45
广西壮族自治区来宾市一辆沃尔沃牌汽车将以25万起拍-天天热议
据阿里资产平台披露,广西壮族自治区象州县人民法院将于2023年7月1日10
-
2023-06-26 22:04:25
全球消息!天津地铁4号线北段工程完成重要节点目标 222天掘进零事故
天津地铁4号线北段工程土建7标西沽公园站-西于庄站区间左线盾构机顺利
-
2023-06-26 21:27:49
全球快播:刚刚,崩了!原因找到
兄弟姐妹们啊,今天又崩了啊,上午泰勒看了一会大盘走势图,以为下午是
-
2023-06-26 20:40:28
天天最新:西藏矿业:公司与日喀则市仲巴县人民政府和倍杰特全资子公司西藏京润签订《日喀则市招商引资项目投资协议书》
西藏矿业(000762):公司与日喀则市仲巴县人民政府和倍杰特(300774)全资
-
2023-06-26 19:56:38
京北方:拟发行可转债募资不超过11.3亿元|环球资讯
京北方公告,拟发行可转债募资不超过11 3亿元,用于盘庚测试云建设项目
-
2023-06-26 19:06:47
400名音美教师开启封闭学习模式
中国教育报-中国教育新闻网讯(记者陈欣然徐德明通讯员刘恒岳)暑期将
-
2023-06-26 18:52:35
头条:端午假期铁路累计发送旅客7037.9万人次 较2019年同期增长11.3%
记者从中国国家铁路集团有限公司(下称国铁集团)获悉,6月25日,为期5
-
2023-06-26 18:24:24
欧股周一盘初下跌 势将创下去年10月以来最长连跌记录
欧洲股市周一下跌,势将连续第六个交易日下跌,上周录得3月中旬以来最
-
2023-06-26 17:56:53
北京限行最新通知外地车_北京限行车号新规定外地车 全球时讯
1、周一至周五每天上午7点到9点,下午5点到8点外地牌照的车不可以进入
-
2023-06-26 17:24:29
兰考县堌阳镇网格员多措并举开展防溺水宣传
夏季是溺水事件的高发季节,为进一步加强防溺水知识宣传,6月25日,
-
2023-06-26 16:49:25
磁翻板液位计如何做好泄漏预防与维护
根据浮力原理和磁性耦合作用研制而成的磁翻板液位计,显示醒目,读数直
-
2023-06-26 16:46:56
港股日报|恒生指数跌0.51%,南向资金净买入31.93亿港元,消费者主要零售商板块领涨 环球速读
截至2023年6月26日港股收盘,恒生指数跌0 51%,报18794 13点;恒生国企
-
2023-06-26 15:54:05
世界观热点:钉钉考勤打卡作弊(钉钉考勤打卡如何作弊)
大家好,小乐来为大家解答以上的问题。钉钉考勤打卡作弊,钉钉考勤打卡
-
2023-06-26 15:56:12
海昌海洋公园迎疫后客流高峰 端午接客人次较2019同期增长超20%
初步统计显示,海昌海洋公园在端午小长假累计接待游客近25万人次,较20
-
2023-06-26 15:20:04
今日热文:写周末的句子
写周末的句子1、周末了,注意休息好哦!2、我要换个地方睡觉觉啦。3、
-
2023-06-26 14:50:22
全球微资讯!标普将中国今年经济按年增速预估下调至5.2%
观点香港网讯:6月26日,标普全球评级表示,将中国今年经济按年增速预
-
2023-06-26 13:56:31
牛磺酸让动物更长寿更健康,是否有助人类抗衰老尚无定论 全球新消息
本报讯一项研究表明,给年老的小鼠、蠕虫和猴子喂食大量牛磺酸(一
-
2023-06-26 13:22:34
康力源6月26日快速反弹-百事通
以下是康力源在北京时间6月26日13:15分盘口异动快照:6月26日,康力源
-
2023-06-26 12:42:36
焦点消息!杭州网约车新门槛:须新车 非新能源纯电动车车价需过15万
【大河财立方消息】日前,杭州市政府办公厅印发《网络预约出租汽车经营
-
2023-06-26 12:04:33
全球热头条丨小猪民宿:端午期间平均客单价比2019年同期增近五成
据小猪民宿数据显示,端午假期期间,小猪民宿订单量已恢复到2019年同期
-
2023-06-26 11:50:48
司法部:准予5家外国律师事务所在华设立代表处
记者从司法部获悉,根据《外国律师事务所驻华代表机构管理条例》的规定
-
2023-06-26 11:05:45
网络产品服务的提供者不得设置恶意程序及时向用户告知 网络产品服务的提供者不得设置
1、对消费者不得条款。相信通过网络产品服务的提供者不得设置这篇文章
-
2023-06-25 16:12:26
桂林多部门开启巡逻!只为做好这件事
随着高考结束、暑假临近,到漓江游泳的人也开始增多。近日,一群与水打
-
2023-06-25 15:49:11
每日观点:如何提高孩子记忆力_提高孩子记忆力的方法
1、首先,在日常生活中,让孩子养成良好的饮食习惯和睡眠习惯。2、尽量
-
2023-06-25 15:00:11
武安镇何家坪村志愿团体 通讯
1、武安镇何家坪村志愿团体是由南漳县志愿者协会领导下的志愿团体。2、
-
2023-06-25 14:35:59
世界观点:11亿美元投资来了!蔚来与阿布扎比投资机构 CYVN Holdings签署认购协议
6月20日晚,蔚来与阿布扎比投资机构CYVNHoldings签署了一份股份认购协