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

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;然后进行…