React源碼2 React中的工廠函數:createRoot()

#React V18.2 源碼

前置基礎知識:工廠函數

工廠函數是一種設計模式,用于動態創建對象或函數實例。其核心思想是通過封裝對象創建的細節,提供統一的接口,從而增強代碼的靈活性和可維護性,有一些核心作用:

  • 解耦創建邏輯:將對象的實例化過程與使用分離,調用方無需關心具體實現細節。
  • 動態生成:根據輸入參數返回不同類型的對象或函數。
  • 統一接口:通過單一入口點管理多種創建場景。

工廠函數由構造函數進階而來,都是用來創建實例。

這是一個函數,KindofNode“某類節點”的構造函數,可以通過new,創建一個實例對象(開辟一塊空間,將原型拷貝到該空間,并將該空間的this指向該實例)。很好理解。

function KindOfNode(kind, properties1, properties2, properties3) {//這是一個構造函數this.kind = kind;this.properties1 = properties1;this.properties2 = properties2;this.properties3 = properties3;
}aNode = new KindOfNode(null, '屬性1', '屬性2', '屬性3'); //創建一個對象console.dir(aNode);
//kindOfNode {
//   kind: null,
//   properties1: '屬性1',
//   properties2: '屬性2',
//   properties3: '屬性3'
// }

create關鍵詞函數,在框架中約定俗成為構造函數(博主觀察發現),讓我們對這個構造函數進行改進,可以發現可以選擇性的對構造出來的實例某些屬性進行賦值。


    function createNode(kind, properties1, properties2, properties3) {//這是一個工廠函數const node = new KindOfNode(kind, properties1, properties2, properties3);if (kind === null || kind === undefined) {node.kind = 'node';}if (kind === 'hostFiber') {node.kind = 'hostFiber';}return node;
    }fa_node = createNode('hostFiber', '屬性1', '屬性2', '屬性3'); //創建一個對象
    fb_node = createNode(null, '屬性1', '屬性2', '屬性3'); //創建一個對象console.dir(fa_node);
    console.dir(fb_node);
    // kindOfNode {
    //   kind: 'hostFiber',
    //   properties1: '屬性1',
    //   properties2: '屬性2',
    //   properties3: '屬性3'
    // }
    // kindOfNode {
    //   kind: 'node',
    //   properties1: '屬性1',
    //   properties2: '屬性2',
    //   properties3: '屬性3'
    // }

    讓我們正式進入createRoot()方法

    相信有了前置知識,代碼看起來不那么費力了。

    在React源碼中,構造函數的使用:通常以"create"關鍵字命名的函數,函數返回一個構造函數實例或者嵌套調用一個"create"關鍵字命名的函數進行嵌套調用

    CreateRoot方法比較復雜,我列舉出了重要"create"關鍵詞的五種。

    這是createRoot過程中完整的函數調用棧,嵌套調用了多種函數:

    其中:

    • exports.createRoot是在node.js中遵循CommanJS標準的包導出。
    • createRoot$1,出于安全性添加的一層。
    • createRoot??createFiber,依此進行react初始化創建。
    • FiberNode構造函數是push進棧最后一個棧幀,運行完后將從上到下依次pop出棧。

    一、createRoot()

    接收(container, options),返回對應React中虛擬DOM對象,其中:

    • container:其中我們在index.html入口文件選擇的真實DOM根節點。
    • options:用于配置這個 React 根節點的對象。(基本用不到這個參數吧)
    //createRoot()
    function createRoot(container, options) {if (!isValidContainer(container)) {throw new Error('createRoot(...): Target container is not a DOM element.');}warnIfReactDOMContainerInDEV(container);var isStrictMode = false;var concurrentUpdatesByDefaultOverride = false;var identifierPrefix = '';var onRecoverableError = defaultOnRecoverableError;var transitionCallbacks = null;if (options !== null && options !== undefined) {{if (options.hydrate) {warn('hydrate through createRoot is deprecated. Use ReactDOMClient.hydrateRoot(container, <App />) instead.');} else {if (typeof options === 'object' && options !== null && options.$$typeof === REACT_ELEMENT_TYPE) {error('You passed a JSX element to createRoot. You probably meant to ' + 'call root.render instead. ' + 'Example usage:\n\n' + '  let root = createRoot(domContainer);\n' + '  root.render(<App />);');}}}if (options.unstable_strictMode === true) {isStrictMode = true;}if (options.identifierPrefix !== undefined) {identifierPrefix = options.identifierPrefix;}if (options.onRecoverableError !== undefined) {onRecoverableError = options.onRecoverableError;}if (options.transitionCallbacks !== undefined) {transitionCallbacks = options.transitionCallbacks;}}var root = createContainer(container, ConcurrentRoot, null, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError);markContainerAsRoot(root.current, container);var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;listenToAllSupportedEvents(rootContainerElement);return new ReactDOMRoot(root);
    }

    二、createContainer()

    function createContainer(containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) {var hydrate = false;var initialChildren = null;return createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError);
    }

    三、createFiberRoot()

    function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the
    // host config, but because they are passed in at runtime, we have to thread
    // them through the root constructor. Perhaps we should put them all into a
    // single type, like a DynamicHostConfig that is defined by the renderer.
    identifierPrefix, onRecoverableError, transitionCallbacks) {var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError);// stateNode is any.var uninitializedFiber = createHostRootFiber(tag, isStrictMode);root.current = uninitializedFiber;uninitializedFiber.stateNode = root;{var _initialState = {element: initialChildren,isDehydrated: hydrate,cache: null,// not enabled yettransitions: null,pendingSuspenseBoundaries: null};uninitializedFiber.memoizedState = _initialState;}initializeUpdateQueue(uninitializedFiber);return root;
    }

    四、createHostRootFiber()

    function createHostRootFiber(tag, isStrictMode, concurrentUpdatesByDefaultOverride) {var mode;if (tag === ConcurrentRoot) {mode = ConcurrentMode;if (isStrictMode === true) {mode |= StrictLegacyMode;{mode |= StrictEffectsMode;}}} else {mode = NoMode;}if ( isDevToolsPresent) {// Always collect profile timings when DevTools are present.// This enables DevTools to start capturing timing at any point–// Without some nodes in the tree having empty base times.mode |= ProfileMode;}return createFiber(HostRoot, null, null, mode);
    }

    五、creteFiber()

    var createFiber = function (tag, pendingProps, key, mode) {// $FlowFixMe: the shapes are exact here but Flow doesn't like constructorsreturn new FiberNode(tag, pendingProps, key, mode);
    };

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

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

    相關文章

    《UE5_C++多人TPS完整教程》學習筆記42 ——《P43 瞄準(Aiming)》

    本文為B站系列教學視頻 《UE5_C多人TPS完整教程》 —— 《P43 瞄準&#xff08;Aiming&#xff09;》 的學習筆記&#xff0c;該系列教學視頻為計算機工程師、程序員、游戲開發者、作家&#xff08;Engineer, Programmer, Game Developer, Author&#xff09; Stephen Ulibarri…

    SQL Server 臨時表、表變量與WITH語句的用法與區別

    引言 在SQL Server數據處理中,臨時表、表變量和WITH語句(CTE)是關鍵的中間結果集管理工具。臨時表適合大數據量操作,表變量優化小數據量場景,而CTE則簡化復雜查詢邏輯。三者選擇需綜合考量數據量級、事務需求及代碼可讀性。本文將深入解析其工作機制,通過實測對比指導場…

    【Android】組件及布局介紹

    一&#xff1a;代碼分析 1&#xff1a;Android界面開發方式 &#xff08;1&#xff09;JavaView&#xff08;傳統視圖系統&#xff09; 這是 Android 早期的開發方式&#xff0c;用 Java 或 Kotlin 代碼配合 XML 布局文件 來構建界面。&#xff08;簡單了解即可&#xff09; 分…

    Android 音視頻 IPC序列化工具-Flattenable

    Android Binder與AIDL與Service使用案例及分析-CSDN博客 講講這個類,被用在Android音視頻中,跨進程序列化反序列化用。與Binder驅動有很強的聯系。位于: feameworks/native/utils/Flattenable.h Flattenable, 譯為令人滿意的。可能是作者十分滿意自己的這些作品吧,起了這…

    文獻學習|全面繪制和建模水稻調控組景觀揭示了復雜性狀背后的調控架構。

    摘要&#xff1a; 解析調控復雜性狀的機制對于推進作物改良至關重要。在此&#xff0c;我們提出了一個全面的水稻&#xff08;Oryza sativa&#xff09;調控組圖譜&#xff0c;涵蓋了來自三個代表性品種的23種不同組織的染色質可及性。我們的研究揭示了117,176個獨特的開放染色…

    Linux的壓縮與解壓縮

    一、使用tar命令進行打包與解包 1.0、tar命令簡介和常用選項 tar命令是Linux中經常使用的歸檔工具&#xff0c;它的主要功能是【對文件或者目錄進行打包歸檔】&#xff0c;歸檔為一個文件&#xff0c;但是并不進行壓縮&#xff1b;tar命令的歸檔操作效果如下&#xff1a; tar命…

    OpenCV+OCR實現弧形文字識別

    以下是基于OpenCV與OCR實現弧形文字識別的完整技術方案&#xff0c;結合了圖像預處理、幾何變換與OCR引擎調用等關鍵步驟&#xff0c;并提供優化技巧&#xff1a;&#x1f50d; 一、技術原理弧形文字識別的核心在于??將彎曲文本轉換為水平直線??&#xff0c;便于OCR引擎處理…

    【保姆級目標檢測教程】Ubuntu 20.04 部署 YOLOv13 全流程(附訓練/推理代碼)

    前言 YOLOv13 是 YOLO 系列的全新一代實時目標檢測框架&#xff0c;在保持極高推理速度的同時顯著提升了檢測精度&#xff0c;廣泛適用于嵌入式部署、工業質檢、智能安防等多種場景。該版本提供了 Nano、Small、Large、X-Large 四種模型規格&#xff0c;用戶可以根據計算資源和…

    【大模型】到底什么是Function Calling和MCP,以及和ReAct推理的關系是什么?

    文章目錄背景&#xff1a;什么是Agent&#xff1f;背景&#xff1a;為什么需要Function Calling或者MCP&#xff1f;Function Calling和MCP在用戶請求中的整體流程Function Calling&#xff08;函數/工具調用&#xff09;MCP (Model Context Protocol)ReAct (Reasoning and Act…

    CANDENCE 17.4 進行元器件緩存更新

    在我從立創商城導入CANDENCE元器件后&#xff0c;在ORCAD放置元器件時出現了下面的錯誤解決辦法&#xff1a;1、在左邊找到 Design Cache文件夾&#xff0c;在文件夾上鼠標右擊選擇 Cleanup Cache2、再放置該元器件&#xff0c;不管這個&#xff0c;點擊確定3、這時候成功放上…

    深入理解Kafka冪等性:原理、邊界與最佳實踐

    一、什么是真正的消息冪等性&#xff1f; 消息系統的冪等性經常被誤解&#xff0c;我們需要明確其精確含義和能力邊界&#xff1a; 1. 正確定義 Kafka冪等性保證的是&#xff1a;在消息傳輸過程中&#xff0c;無論因網絡重試、生產者重啟等故障導致的消息重復發送&#xff0c;B…

    【RTSP從零實踐】8、多播傳輸H264碼流的RTSP服務器——最簡單的實現例子(附帶源碼)

    &#x1f601;博客主頁&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客內容&#x1f911;&#xff1a;&#x1f36d;嵌入式開發、Linux、C語言、C、數據結構、音視頻&#x1f36d; &#x1f923;本文內容&#x1f923;&a…

    【Linux】基礎開發工具(3)

    1. 版本控制器Git1.1 Git的簡史Git 的歷史可以追溯到 2005 年1。當時 Linux 內核項目的開發團隊一直使用 BitKeeper 進行版本管理&#xff0c;但由于一位 Linux 開發成員寫了一個連接 BitKeeper 倉庫的外掛&#xff0c;BitMover 公司決定中止 Linux 免費使用 BitKeeper 的授權1…

    synchronized 的使用和特性

    synchronized 鎖對象 普通方法 synchronized 鎖普通方法時&#xff0c;其鎖的對象是調用該方法的實例 public synchronized void method() { // 方法體 } 靜態方法 靜態方法的鎖對象是所屬的 class&#xff0c;全局只有一個。 public static synchronized void staticMetho…

    Gin Web 層集成 Viper 配置文件和 Zap 日志文件指南(下)

    在微服務架構中&#xff0c;Gin 常被用作 Web 層框架&#xff0c;而 Viper 用于管理配置文件&#xff0c;Zap 則提供高性能的日志記錄功能。下面將詳細介紹如何在 Gin Web 層集成 Viper 配置文件和 Zap 日志文件。 1. 項目概述 假設我們有一個基于 Go 語言的微服務項目&#…

    IoTDB:專為物聯網場景設計的高性能時序數據庫

    什么是IoTDB&#xff1f;IoTDB&#xff08;Internet of Things Database&#xff09;是一款開源的時序數據庫管理系統&#xff0c;專為物聯網&#xff08;IoT&#xff09;場景設計&#xff0c;由清華大學軟件學院團隊自研&#xff0c;天謀科技團隊負責維護。它針對物聯網數據的…

    [netty5: MessageAggregator HttpObjectAggregator]-源碼解析

    在閱讀這篇文章前&#xff0c;推薦先閱讀 [netty5: ByteToMessageCodec & MessageToByteEncoder & ByteToMessageDecoder]-源碼分析[netty5: HttpObject]-源碼解析 100-continue 100-continue 是 HTTP/1.1 協議中的一種機制&#xff0c;用于客戶端在發送大體積請求體…

    前端學習1--行內元素 vs 塊級元素(基礎概念+案例實操)

    一、內外邊距學習&#xff1a;&#xff08;1&#xff09;簡單理解&#xff1a;padding為內邊距。padding不會影響元素的位置&#xff0c;只會調整元素的內容&#xff08;文字&#xff09;與邊框之間的間距。margin為外邊距。margin會影響元素在流式布局中的位置&#xff0c;改變…

    Express + mysql2 + jwt 實現簡單的登錄鑒權

    目前項目中使用Express 實現簡單API功能&#xff0c;需要提供一套登錄鑒權方案。這邊是API側實現 相關路由的登錄鑒權。大體思路&#xff1a;就是&#xff0c;登錄接口中通過jwt加密 token返回前端&#xff0c;前端其他接口把加密好的放入請求頭Authorization中。中間件通過請求…

    ReAct (Reason and Act) OR 強化學習(Reinforcement Learning, RL)

    這個問題觸及了現代AI智能體&#xff08;Agent&#xff09;構建的兩種核心思想。 簡單來說&#xff0c;ReAct 是一種“調用專家”的模式&#xff0c;而強化學習 (RL) 是一種“從零試錯”的模式。 為了讓你更清晰地理解&#xff0c;我們從一個生動的比喻開始&#xff0c;然后進行…