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開發中非常常見,它們有助于提高代碼的可維護性、可擴展性和重用性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72145.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72145.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72145.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【MATLAB例程】三維下的IMM(交互式多模型),模型使用CV(勻速)和CA(勻加速)

給出三維下的交互式多模型&#xff08;IMM&#xff09;matlab例程&#xff0c;模型使用勻速運動CV和勻加速運動CA&#xff0c;濾波使用EKF&#xff08;擴展卡爾曼濾波&#xff09; 文章目錄 代碼運行結果程序結構 代碼講解模型定義&#xff1a;軌跡生成&#xff1a;IMM核心流程…

物理內存組織與分配的核心概念

在 Linux 內核內存管理&#xff08;尤其是 Buddy System 伙伴系統&#xff09;中&#xff0c;node、zone、type 和 order 是描述物理內存組織與分配的核心概念。以下是它們的詳細解釋&#xff1a; 1. Node&#xff08;NUMA 節點&#xff09; 定義&#xff1a; 在 NUMA&#xf…

智科技賦能寵物關懷新時代

在科技日新月異的今天&#xff0c;智能寵物監控技術正悄然引領寵物護理領域的新變革。借助尖端的傳感器技術、高清攝像頭以及強大的數據分析能力&#xff0c;這些智能系統為寵物主人開辟了前所未有的寵物關懷途徑&#xff0c;讓愛與關懷跨越時空限制。 智能寵物監控系統的核心…

SOME/IP 教程知識點總結

總結關于SOME/IP的教程,首先通讀整個文件,理解各個部分的內容。看起來這個教程從介紹開始,講到了為什么在車輛中使用以太網,然后詳細講解了SOME/IP的概念、序列化、消息傳遞、服務發現(SOME/IP-SD)、發布/訂閱機制以及支持情況。 首先,我需要確認每個章節的主要知識點。…

playbin之autoplug_factories源碼剖析

一、autoplug_factories_cb /* Called when we must provide a list of factories to plug to pad with caps.* We first check if we have a sink that can handle the format and if we do, we* return NULL, to expose the pad. If we have no sink (or the sink does not…

58區間和+44開發商購買土地(前綴和)

58. 區間和&#xff08;第九期模擬筆試&#xff09; 題目描述 給定一個整數數組 Array&#xff0c;請計算該數組在每個指定區間內元素的總和。 輸入描述 第一行輸入為整數數組 Array 的長度 n&#xff0c;接下來 n 行&#xff0c;每行一個整數&#xff0c;表示數組的元素。…

laravel11設置中文語言包

安裝中文語言包 Laravel 11 默認沒有內置完整中文語言包&#xff0c;推薦使用第三方維護的完整翻譯&#xff1a; # 通過 Composer 安裝語言包 composer require laravel-lang/common --dev# 發布中文語言文件到項目 php artisan lang:add zh_CN這會自動將中文語言文件生成到 l…

智能文檔解析與語義分割:LlamaIndex 節點解析器模塊全解

節點解析器模塊 - LlamaIndex 文件內容的節點解析器 有幾種基于文件的節點解析器,它們會根據解析的內容類型(JSON、Markdown 等)創建節點。 最簡單的流程是將 FlatFileReader 與 SimpleFileNodeParser 結合使用,自動為每種內容類型選擇最佳節點解析器。然后,可以將基于…

實現遍歷Windows所有字體的基本屬性

參考podofo #include <windows.h> #include <string> #include <memory> #include <set> #include <unordered_map> #include <vector> #include <algorithm> #include <iostream> #include <iomanip> #include <fst…

postman--接口測試工具安裝和使用教程

postman–接口測試工具 postman是一款支持http協議的接口調試與測試工具&#xff0c;其主要特點就是功能強大&#xff0c;使用簡單且易用性好 。 無論是開發人員進行接口調試&#xff0c;還是測試人員做接口測試&#xff0c;postman都是我們的首選工具之一 。 下面先通過一張…

綜合練習 —— 遞歸、搜索與回溯算法

目錄 一、1863. 找出所有子集的異或總和再求和 - 力扣&#xff08;LeetCode&#xff09; 算法代碼&#xff1a; 代碼思路 問題分析 核心思想 實現細節 代碼解析 初始化 DFS 函數 時間復雜度 空間復雜度 示例運行 輸入 運行過程 總結 二、 47. 全排列 II - 力扣&a…

代碼隨想錄算法訓練day64---圖論系列8《拓撲排序dijkstra(樸素版)》

代碼隨想錄算法訓練 —day64 文章目錄 代碼隨想錄算法訓練前言一、53. 117. 軟件構建—拓撲排序二、47. 參加科學大會---dijkstra&#xff08;樸素版&#xff09;總結 前言 今天是算法營的第64天&#xff0c;希望自己能夠堅持下來&#xff01; 今天繼續圖論part&#xff01;今…

學術小助手智能體

學術小助手&#xff1a;開學季的學術領航員 文心智能體平臺AgentBuilder | 想象即現實 文心智能體平臺AgentBuilder&#xff0c;是百度推出的基于文心大模型的智能體平臺&#xff0c;支持廣大開發者根據自身行業領域、應用場景&#xff0c;選取不同類型的開發方式&#xff0c;…

JavaScript 簡單類型與復雜類型-復雜類型傳參

在JavaScript中&#xff0c;變量根據其存儲的數據類型可分為簡單類型&#xff08;基本數據類型&#xff09;和復雜類型&#xff08;引用數據類型&#xff09;。理解這兩者在函數調用時的行為差異對于編寫高效且無誤的代碼至關重要。本文將專注于探討復雜類型的參數傳遞機制&…

L2-043 龍龍送外賣(dfs)

龍龍是“飽了呀”外賣軟件的注冊騎手&#xff0c;負責送帕特小區的外賣。帕特小區的構造非常特別&#xff0c;都是雙向道路且沒有構成環 —— 你可以簡單地認為小區的路構成了一棵樹&#xff0c;根結點是外賣站&#xff0c;樹上的結點就是要送餐的地址。 每到中午 12 點&#…

如何基于PyTorch做二次開發

基于PyTorch進行二次開發以實現可視化工程&#xff0c;可以從以下幾個方面入手&#xff1a;模型結構可視化、訓練過程監控、特征可視化等。以下是一些推薦的GitHub項目&#xff0c;這些項目可以幫助你快速搭建一個可視化的工程環境&#xff1a; ### 1. **PyTorch CNN Visualiz…

本地大模型編程實戰(26)用langgraph實現基于SQL數據構建的問答系統(5)

本文將將擴展上一篇文章完成的 langgraph 鏈&#xff0c;繼續使用基于 langgraph 鏈 &#xff0c;對結構化數據庫 SQlite 進行查詢的方法。該系統建立以后&#xff0c;我們不需要掌握專業的 SQL 技能&#xff0c;可以用自然語言詢問有關數據庫中數據的問題并返回答案。主要完善…

【Kubernetes】污點和容忍

一、概述 在 Kubernetes&#xff08;k8s&#xff09;中&#xff0c;污點&#xff08;Taints&#xff09; 是定義在節點上的一種機制&#xff0c;用于拒絕某些 Pod 調度到該節點&#xff0c;除非這些 Pod 具有對應的容忍度&#xff08;Tolerations&#xff09;。污點可以用來控…

【大模型?知識圖譜】大模型結合醫療知識圖譜:解鎖智能輔助診療系統新范式

【大模型?知識圖譜】大模型結合醫療知識圖譜:解鎖智能輔助診療系統新范式 大模型結合醫療知識圖譜:解鎖智能輔助診療系統新范式引言一、系統架構1.1 系統架構圖1.2 架構模塊說明1.2.1 用戶輸入1.2.2 大模型(語義理解與意圖識別)1.2.3 Agent(問題解析與任務分配)1.2.4 問…

FASIONAD:自適應反饋的類人自動駕駛中快速和慢速思維融合系統

24年11月來自清華、早稻田大學、明尼蘇達大學、多倫多大學、廈門大學馬來西亞分校、電子科大&#xff08;成都&#xff09;、智平方科技和河南潤泰數字科技的論文“FASIONAD : FAst and Slow FusION Thinking Systems for Human-Like Autonomous Driving with Adaptive Feedbac…