最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

組件結(jié)構(gòu) - 在React中構(gòu)建可重用和可維護的組件

2023-06-27 06:41 作者:曉楓Motivation  | 我要投稿

我們將探討組件結(jié)構(gòu)的重要性以及它如何有助于創(chuàng)建高度可重用、模塊化且易于維護的組件。

在 React 中構(gòu)建可重用和可維護的組件不僅僅是編寫代碼;還需要編寫代碼。它涉及采用最佳實踐并遵循合理的架構(gòu)原則。

通過仔細構(gòu)建我們的組件,遵守單一職責原則,并采用原子設計和組件組合等概念,我們可以創(chuàng)建更加模塊化、更易于測試和更易于維護的代碼。

這種方法可以實現(xiàn)更高效的開發(fā)過程,并最終產(chǎn)生高質(zhì)量、可擴展的 React 應用程序。

(更|多優(yōu)質(zhì)內(nèi)|容:java567 點 c0m)


讓我們考慮一個在 React 中實現(xiàn)的 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(e.target.value);
? ?};
?
? // Handle todo logic ?
? ?const handleAddTodo = () => {
? ? ?if (newTodo.trim() !== '') {
? ? ? ?const updatedTodos = [...todos, newTodo];
? ? ? ?setTodos(updatedTodos);
? ? ? ?setNewTodo('');
? ? ?}
? ?};
?
? ?const handleDeleteTodo = (index) => {
? ? ?const updatedTodos = todos.filter((_, i) => i !== index);
? ? ?setTodos(updatedTodos);
? ?};
?
? ?const handleCompleteTodo = (index) => {
? ? ?const updatedTodos = todos.map((todo, i) => {
? ? ? ?if (i === index) {
? ? ? ? ?return { ...todo, completed: !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>
? ? ? ? ?{todos.map((todo, index) => (
? ? ? ? ? ?<li key={index}>
? ? ? ? ? ? ?<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.text}</span>
? ? ? ? ? ? ?<button onClick={() => handleDeleteTodo(index)}>Delete</button>
? ? ? ? ? ? ?<button onClick={() => handleCompleteTodo(index)}>
? ? ? ? ? ? ? ?{todo.completed ? 'Mark Incomplete' : 'Mark Complete'}
? ? ? ? ? ? ?</button>
? ? ? ? ? ?</li>
? ? ? ? ?))}
? ? ? ?</ul>
? ? ?</div>
? ?);
?};


上面的代碼庫包含一個組件,它處理從呈現(xiàn) UI到處理數(shù)據(jù)和狀態(tài)管理的所有事務。這種單一的方法導致缺乏關(guān)注點分離,并且違反了SRP和原子設計原則。

為了改進代碼,我們可以遵循SRP和原子設計原則:

單一職責原則(SRP)

該原則指出,類或組件應該有單一的職責或單一的更改原因。通過使組件專注于特定任務,您可以提高代碼的可讀性、可維護性和可重用性。

它促進將復雜的功能分解為更小、更集中的部分,更容易理解、測試和維護。

它鼓勵組件有明確和具體的職責,增強其可重用性和可維護性。

它通過讓組件專注于特定任務來幫助避免緊密耦合的組件。

讓我們分解一下整體,

  • TodoInput:將輸入處理邏輯提取到單獨的useTodoInput自定義掛鉤和組件中TodoInput。

負責處理用戶輸入并添加新的待辦事項。

  • TodoList:將待辦事項列表處理邏輯提取到單獨的useTodoList自定義掛鉤和組件中TodoList。

負責呈現(xiàn)待辦事項列表。

  • TodoItem:將各個待辦事項的渲染邏輯移至單獨的TodoItem組件中。

負責渲染單個待辦事項。

通過將狀態(tài)和事件處理邏輯分離到自定義掛鉤或組件中,我們確保每個組件都有以下單一職責。

待辦事項輸入

useTodoInput自定義掛鉤可以使用 useState 掛鉤管理輸入狀態(tài)并處理輸入更改事件

使用TodoInput.js

?// ? 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) => {
? ? ?e.preventDefault();
? ? ?onAddTodo(inputValue);
? ? ?clearInput();
? ?};
?
? ?const handleInputChange = (e) => {
? ? ?const value = e.target.value;
? ? ?setInputValue(value);
? ? ?setDisabled(value.trim() === "");
? ?};
?
? ?const clearInput = () => {
? ? ?setInputValue("");
? ? ?setDisabled(true);
? ?};
?
? ?return {
? ? ?disabled,
? ? ?inputValue,
? ? ?handleInputChange,
? ? ?handleSubmit
? ?};
?};
?
?export { useTodoInput };


通過使用自定義鉤子,我們可以以可重用和模塊化的方式封裝狀態(tài)和事件處理邏輯,從而提高代碼的可重用性和可維護性。

TodoInput.jsx

將與輸入字段、“添加待辦事項”按鈕和待辦事項列表相關(guān)的 JSX 代碼移至單獨的 JSX 文件中。

?// TodoInput.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 代碼分成單獨的文件,我們可以提高代碼的組織性和可讀性,從而更容易維護和理解組件結(jié)構(gòu)。

像這樣我們需要拆分TodoItem和TodoList。

這種重構(gòu)方法通過為每個組件分配單一職責來遵守 SRP,利用自定義掛鉤進行狀態(tài)和事件處理,并將 JSX 代碼分離為可重用的組件,從而提高 React 應用程序的模塊化性和可維護性。

最后,組件結(jié)構(gòu)如下所示,

?// ? Component Stucture
?
?components/
?├── todo-input/
?│ ? ├── TodoInput.jsx
?│ ? ├── useTodoInput.js
?│ ? └── TodoInput.css
?├── todo-item/
?│ ? ├── TodoItem.jsx
?│ ? └── TodoItem.css
?├── todo-list/
?│ ? ├── TodoList.jsx
?│ ? ├── useTodoList.js
?│ ? └── TodoList.css
?└── ...


您可以在codesandbox 中查看整個代碼庫。


我們可以使用原子設計原則進一步重構(gòu)這個代碼庫。

原子設計原理

原子設計是一種根據(jù)組件的抽象級別和復雜性以分層方式設計和組織組件的方法。

它將組件分為五個級別:原子、分子、有機體、模板和頁面,每個級別都有特定的職責。

  • 原子:在最低級別,原子代表最小和最基本的 UI 元素,例如按鈕、輸入或圖標。

他們有單一的職責,專注于其視覺外觀和基本功能。

  • 分子:分子是原子的組合,它們共同作用以創(chuàng)建更復雜的 UI 元素。

它們的責任級別稍高,代表一組相關(guān)的原子。

  • 有機體:有機體由分子和原子組成,代表用戶界面更大、更獨立的部分。

它們具有更復雜的行為,可能包括狀態(tài)管理和交互邏輯。

  • 模板:模板是有機體的特定排列,為頁面或部分提供基本結(jié)構(gòu)。

它們定義了 UI 的整體布局和組成。

  • 頁面:頁面是用真實數(shù)據(jù)填充模板的實例,創(chuàng)建供用戶交互的實際內(nèi)容。

讓我們以同一個待辦事項應用程序為例。我將使用原子設計模式給出高級代碼設計:

原子

Atoms 包含小型、可重用的 UI 組件,例如Button和Input。

?// ? Atoms
?
?// Button.jsx
?const Button = ({ onClick, children }) => {
? ?return (
? ? ?<button className="button" onClick={onClick}>
? ? ? ?{children}
? ? ?</button>
? ?);
?};
?
?//Input.jsx
?const Input = ({ value, onChange }) => {
? ?return (
? ? ?<input className="input" type="text" value={value} onChange={onChange} />
? ?);
?};


每個原子都有自己的 JavaScript 文件 ( Button.jsx, Input.jsx) 和 CSS 文件 ( Button.css, Input.css)。

分子

分子目錄包含形成更復雜組件的原子組合 (Button.jsx),例如 TodoItem組件。

?// ? Molecules
?
?// TodoItem.jsx
?const TodoItem = ({ todo, onDelete, onComplete }) => {
? ?return (
? ? ?<li className="todo-item">
? ? ? ?<span className={todo.completed ? 'completed' : ''}>{todo.text}</span>
? ? ? ?<Button onClick={onDelete}>Delete</button>
? ? ? ?<Button onClick={onComplete}>
? ? ? ? ?{todo.completed ? 'Mark Incomplete' : 'Mark Complete'}
? ? ? ?</Button>
? ? ?</li>
? ?);
?};


它有自己的 JavaScript 文件 ( TodoItem.js ) 和 CSS 文件 ( TodoItem.css )。

生物體

有機體目錄包含更大、功能更豐富的組件,例如TodoForm和TodoList組件。

?// ? Organisms
?
?// TodoForm.jsx
?const TodoForm = ({ onAddTodo }) => {
? ?const {inputChange, addTodo} = useTodoForm();
?
? ?return (
? ? ?<div className="todo-form">
? ? ? ?<Input value={newTodo} onChange={inputChange} />
? ? ? ?<Button onClick={addTodo}>Add Todo</Button>
? ? ?</div>
? ?);
?};
?
?// TodoList.jsx
?const TodoList = ({ todos, onDeleteTodo, onCompleteTodo }) => {
? ?return (
? ? ?<ul className="todo-list">
? ? ? ?{todos.map((todo, index) => (
? ? ? ? ?<TodoItem
? ? ? ? ? ?key={index}
? ? ? ? ? ?todo={todo}
? ? ? ? ? ?onDelete={() => onDeleteTodo(index)}
? ? ? ? ? ?onComplete={() => onCompleteTodo(index)}
? ? ? ? ?/>
? ? ? ?))}
? ? ?</ul>
? ?);
?};


它們由分子和/或原子組成,并有自己的 JSX(TodoForm.jsx、TodoList.jsx)、自定義 Hooks(useTodoForm.js)和CSS文件。

模板

模板包含提供頁面或布局整體結(jié)構(gòu)的組件。在這種情況下,Todo模板負責呈現(xiàn)TodoForm和TodoList組件。

?// ? Templates
?
?// Todo.jsx
?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 文件 ( Todo.jsx) 和自定義 Hook ( useTodo.js) 以及 CSS 文件 ( Todo.css)。

頁數(shù)

代表應用程序中特定頁面的頁面目錄組件。在此示例中,有一個HomePage組件充當 Todo 應用程序的主入口點。

?// ? Pages
?
?// HomePage.js
?const HomePage = () => {
? ?return (
? ? ?<div className="home-page">
? ? ? ?<TodoApp />
? ? ?</div>
? ?);
?};


此示例演示了如何使用原子設計模式構(gòu)建 Todo 應用程序代碼庫。每個組件負責一個關(guān)注點,并且可以輕松地重用和組合它們以構(gòu)建完整的 Todo 應用程序。

最后的想法

設計 React 應用程序時,必須避免將多個職責分配給單個組件。以下是一些實用策略,可幫助您實現(xiàn)更清晰、更易于維護的代碼庫:

1. 明確職責:明確定義每個組件的目的。將復雜的功能分解為更小、更集中的組件,并具有明確的職責。

2. 關(guān)注點分離:根據(jù)應用程序的功能將應用程序劃分為不同的組件來分離關(guān)注點。每個組件都應該具有特定的角色并處理單一的職責。

3. 組件組合:不要構(gòu)建處理多個任務的大型組件,而是通過組合較小的、可重用的組件來組合您的 UI。這促進了可重用性和模塊化。

4. 單任務功能:將復雜的邏輯從組件中提取到單獨的功能或?qū)嵱媚K中。通過將特定功能封裝在單獨的函數(shù)中,您可以使組件專注于渲染和 UI 相關(guān)任務。

5. 遵循 SOLID 原則:遵守 SOLID 原則,例如單一職責原則 (SRP),該原則規(guī)定組件應該只有一個更改理由。這一原則可幫助您設計專注、可維護且更易于測試的組件。

6. 使用自定義鉤子:將通用邏輯提取到可以跨組件共享的自定義鉤子中。這允許您重用邏輯,而不會給各個組件帶來不必要的復雜性。

7. 模塊化架構(gòu):使用模塊化架構(gòu)組織代碼庫,例如基于功能的文件夾結(jié)構(gòu)。這種方法促進了關(guān)注點的分離,并有助于使組件專注于其特定的職責。

通過有意識地根據(jù)這些實踐來設計 React 應用程序,您可以避免向組件分配多重職責。這會帶來更干凈、更易于維護的代碼,更容易理解、測試和擴展。

獎勵 - 組件層次結(jié)構(gòu)

通常建議遵循特定的組件層次結(jié)構(gòu),以保持代碼庫的一致性和可讀性。

?// ? 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 './Component.css';
?import '../styles/common.css';
?
?// Assets
?import todoImage from '../assets/todoImage.png';
?
?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>
? ?);
?}
?
?Todo.propTypes = {
? ?// Prop types declaration
?};
?
?export { Todo };


通過以一致且有組織的方式構(gòu)建組件層次結(jié)構(gòu),您可以提高 React 應用程序的可讀性、可維護性和可擴展性。

定義良好的層次結(jié)構(gòu)可幫助開發(fā)人員瀏覽代碼庫、理解組件關(guān)系并高效地進行修改。

請繼續(xù)關(guān)注我未來的博客文章中有關(guān)構(gòu)建高質(zhì)量 React 應用程序的更多提示和技巧!

快樂編碼!????????????

(更|多優(yōu)質(zhì)內(nèi)|容:java567 點 c0m)


組件結(jié)構(gòu) - 在React中構(gòu)建可重用和可維護的組件的評論 (共 條)

分享到微博請遵守國家法律
荥阳市| 亳州市| 红河县| 凤庆县| 玉树县| 彰化县| 惠水县| 雷波县| 稷山县| 云梦县| 灵石县| 四平市| 松溪县| 呼图壁县| 太仆寺旗| 巫山县| 和林格尔县| 柏乡县| 永平县| 浮梁县| 德钦县| 广西| 余姚市| 岳西县| 琼海市| 开平市| 万盛区| 栾川县| 钟山县| 柳林县| 瑞安市| 五原县| 精河县| 津市市| 桃江县| 南郑县| 平塘县| 上饶市| 梁河县| 冷水江市| 卢氏县|