React渲染和更新机制及其核心内容详解

0.Overview

步骤 1: 触发一次渲染 

初次渲染 

当应用启动时,会触发初次渲染。它是通过调用目标 DOM 节点的 createRoot,然后用你的组件调用 render 函数完成的:

//index.js
import Image from './Image.js';
import { createRoot } from 'react-dom/client';const root = createRoot(document.getElementById('root'))
root.render(<Image />);//Image.js
export default function Image() {return (<imgsrc="https://i.imgur.com/ZF6s192.jpg"alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals"/>);
}
 状态更新时重新渲染 

     一旦组件被初次渲染,你就可以通过使用 set 函数 更新其状态来触发之后的渲染。更新组件的状态会自动将一次渲染送入队列

步骤 2: React 渲染你的组件 

  • 在进行初次渲染时, React 会调用根组件。
  • 对于后续的渲染, React 会调用内部状态更新触发了渲染的函数组件。

这个过程是递归的:如果更新后的组件会返回某个另外的组件,那么 React 接下来就会渲染 那个 组件,而如果那个组件又返回了某个组件,那么 React 接下来就会渲染 那个 组件,以此类推。这个过程会持续下去,直到没有更多的嵌套组件并且 React 确切知道哪些东西应该显示到屏幕上为止。

步骤 3: React 把更改提交到 DOM 上 

在渲染(调用)你的组件之后,React 将会修改 DOM。

  • 对于初次渲染, React 会使用 appendChild() DOM API 将其创建的所有 DOM 节点放在屏幕上。
  • 对于重渲染, React 将应用最少的必要操作(在渲染时计算!),以使得 DOM 与最新的渲染输出相互匹配。

React 仅在渲染之间存在差异时才会更改 DOM 节点。 例如,有一个组件,它每秒使用从父组件传递下来的不同属性重新渲染一次。注意,你可以添加一些文本到 <input> 标签,更新它的 value,但是文本不会在组件重渲染时消失:

React 的渲染和更新流程是其核心机制之一,它负责确保 UI 与应用状态保持一致。以下是详细的解析,包括渲染流程、更新流程,以及它们涉及的核心概念和机制。


一、React 渲染流程

当 React 应用第一次加载时,会经历以下的渲染流程:

1. 初次渲染

初次渲染是从根组件开始,递归构建整个组件树,生成 UI,直至页面呈现。

流程步骤:
  1. 创建 React 元素树: React 的 JSX 被转换成 JavaScript 对象(即 React 元素),这些元素描述了 UI 的结构。

  1. 构建 Fiber 树

    • React 会将 React 元素转换为内部的 Fiber 数据结构
    • Fiber 是 React 的核心工作单元,表示组件的信息和其状态。
  2. Reconciliation (协调过程)

    • React 开始从根组件递归遍历,调用组件的 render 方法,生成虚拟 DOM。
    • 如果是函数组件,会直接执行该函数;如果是类组件,会实例化类,调用其 render 方法。
  3. Commit 阶段 (提交真实 DOM)

    • 将生成的虚拟 DOM 转换为真实 DOM,并挂载到页面。
    • 在这一阶段,React 会执行副作用(如 useEffectcomponentDidMount)。

    主要分为两部分

    • Before Mutation:更新前的一些操作(例如记录 DOM 状态)。
    • Mutation:操作真实 DOM(如插入、更新或删除 DOM 节点)。

 

二、React 更新流程

当组件的 stateprops 发生变化时,会触发更新流程。React 的更新流程主要包括以下步骤:

1. 触发更新

  • 当组件调用 setState 或接收新的 props 时,React 标记该组件为需要更新。

2. Scheduler 调度更新

  • 调度优先级:React 根据任务的优先级(例如用户输入的更新比动画更紧急)决定何时开始工作。
  • React 依赖 时间切片 (Time Slicing),将任务分成多个小块,并在浏览器空闲时执行。

3. Reconciliation (协调过程)

  • 比较更新前后的 Fiber 树(即 Diff 算法)。
  • 如果两个 Fiber 节点表示相同的元素,保留原有的 DOM 节点;如果不同,则生成新的 DOM 节点。

主要策略

  • 类型相同的节点:更新属性并复用 DOM 节点。
  • 类型不同的节点:销毁旧节点,创建新节点。
  • 列表的 Diff 算法:根据 key 属性优化节点的复用。

4. Commit 阶段

  • 完成虚拟 DOM 的更新后,React 提交更改到真实 DOM。
  • 执行 DOM 操作(如插入、删除、更新)。
  • 执行副作用(如 useEffectcomponentDidUpdate

 

三、React 的核心内容详解

1. Fiber 架构

  • Fiber 是 React 16 引入的调度算法,核心目标是实现 可中断的渲染
  • 每个组件对应一个 Fiber 节点,记录了组件的类型、状态、DOM 引用等。

特点

  • 可中断:React 将渲染分成多个任务,可以随时暂停或恢复。
  • 优先级:不同任务有不同的优先级(如用户输入 > 数据加载)。

2. 时间切片 (Time Slicing)

  • React 使用 requestIdleCallbackMessageChannel 模拟时间切片。
  • 当渲染任务较重时,React 会暂停渲染,将控制权交还给浏览器,保证界面流畅性。

3. Reconciliation (Diff 算法)

  • React 使用了一种 O(n) 的算法,而不是传统虚拟 DOM 的 O(n^3)
  • 核心是通过 key 和节点类型快速判断节点是否需要更新。

4. Scheduler 调度

  • React 内置 Scheduler,通过任务优先级和调度机制实现任务分配。
  • 优先级分类
    • Immediate:同步任务(如 setState 的同步模式)。
    • User-blocking:如用户输入。
    • Normal:常规更新。
    • Low:非关键更新。
    • Idle:空闲时执行的任务。

5. Hooks 的依赖收集

  • 对于 useEffectuseMemo,React 会根据依赖数组 [dependencies] 判断是否需要重新执行。

 

四、示例讲解:从渲染到更新

初次渲染示例

function App() {const [count, setCount] = React.useState(0);return (<div><h1>Count: {count}</h1><button onClick={() => setCount(count + 1)}>Increment</button></div>);
}
  1. 初次渲染

    • 调用 App 函数,生成虚拟 DOM。
    • 构建 Fiber 树,将虚拟 DOM 提交为真实 DOM。
  2. 点击更新

    • 点击按钮触发 setCount,React 标记 App 为需要更新。
    • React 比较前后 Fiber 树,发现 h1 的内容需要更新。
    • 提交更改,仅更新 h1 的内容,而不会重新创建整个 DOM。

五、优化点

  1. 避免不必要的更新
    • 使用 React.memouseMemo 缓存组件和计算结果。
  2. 合理设置 key
    • 为列表的每个元素分配唯一且稳定的 key,避免重复渲染。
  3. 按需加载
    • 使用动态加载(如 React.lazy)减小初次渲染的体积。

———————————————————————————————————————————

六、值得关注的点 

在React的渲染流程中,除了基本的流程框架外,还有一些细节值得关注,它们对于理解和优化React应用具有重要意义。以下是一些关键的细节:

1. 渲染流程的阶段划分

  • Render阶段(协调阶段):这个阶段主要是进行虚拟DOM的比较和更新计划的制定。React会在这个阶段调用组件的render方法(或函数体),生成新的虚拟DOM,并与旧的虚拟DOM进行比较,找出差异点,并标记需要更新的Fiber节点。
  • Commit阶段:这个阶段主要是将更新同步到实际的DOM中。React会在这个阶段执行DOM操作,例如创建、更新或删除DOM元素,以反映组件树的最新状态。

2. Fiber架构的引入

  • React 16引入了Fiber架构,实现了异步可中断的渲染。Fiber将渲染工作分解为一个个小的任务单元,每个任务单元称为Fiber节点。
  • 在渲染过程中,如果有更高优先级的任务出现(如用户交互),渲染可以被中断,优先处理高优先级任务。这使得React能够更好地响应用户操作,提供更流畅的用户体验。

3. 调度器(Scheduler)的作用

  • 调度器负责为任务排序优先级,让优先级高的任务先进入到协调器进行处理。
  • 调度器在浏览器的原生API中有类似的实现(如requestIdleCallback),但React团队为了实现更稳定和兼容的调度机制,自己实现了一套调度器。

4. 副作用(Effects)的处理

  • 在React中,副作用是指那些会影响组件外部状态的操作,如数据获取、订阅事件、手动修改DOM等。
  • 在Render阶段,React会收集这些副作用,并在Commit阶段执行它们。这样可以确保副作用在DOM更新之后执行,避免潜在的竞争条件。

5. 虚拟DOM的比较算法(Diff算法)

  • React使用了一种高效的Diff算法来比较新旧虚拟DOM树的差异。
  • 该算法采用了深度优先遍历和启发式算法等优化策略,以减少不必要的DOM操作和提高渲染性能。

6. 批量更新和异步执行

  • React的setState机制是“批量更新”和“异步执行”的。
  • 这意味着不会因为每个setState调用立即触发重新渲染,而是在所有更新完成后,进行一次统一的重新渲染。这有助于减少不必要的频繁渲染,提高应用的性能和响应性。

7. 错误边界(Error Boundaries)

  • React提供了错误边界组件来捕获组件渲染过程中的错误。
  • 错误边界组件是一个具有特定生命周期方法的类组件(如getDerivedStateFromError和componentDidCatch)。当子组件在渲染过程中抛出错误时,错误边界组件可以捕获该错误,并展示一个备用的UI,而不是让整个应用崩溃。

8. 渲染流程的中断和恢复

  • Render阶段的工作流程是可以随时被打断的,原因可能包括有其他更高优先级的任务需要执行、当前的time slice没有剩余的时间等。
  • 由于Render阶段的工作是在内存里面进行的,不会更新宿主环境UI,因此这个阶段即使工作流程反复被中断,用户也不会看到更新不完全的UI。

综上所述,React的渲染流程是一个复杂而高效的过程,涉及多个阶段和细节。通过深入理解这些细节,可以更好地优化React应用的性能和响应性,提高用户体验。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19929.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

深入探索Python数据可视化:自定义颜色映射、标签与进阶技巧

目录 一、自定义颜色映射&#xff08;Cmap&#xff09; 1. 内置Cmap类型 2. 使用内置Cmap 3. 自定义Cmap 二、标签添加 1. 在散点图上添加标签 2. 在折线图上标记关键点 3. 在柱状图上添加标签 三、进阶技巧 1. 多图形布局 2. 添加图例 3. 3D数据可视化 四、总结 …

【Java SE】数据库连接池

数据库连接池是一个管理数据库连接的容器。它的主要作用是分配和管理数据库连接&#xff0c;允许应用程序重复使用现有的连接&#xff0c;而不是每次都重新建立新的连接。此外&#xff0c;连接池会释放那些空闲时间超过最大限制的连接&#xff0c;从而避免因未及时释放连接而造…

FastAPI重载不生效?解决PyCharm中Uvicorn无法重载/重载缓慢的终极方法!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 重载缓慢 📒📝 问题概述🚨 相关原因📝 解决方案一📝 解决方案二📝 解决方案三📝 解决方案四⚓️ 相关链接 ⚓️📖 介绍 📖 在使用FastAPI开发时,reload=True 本应让你在修改代码后自动重启服务,提升开发效率…

CPU算法分析LiteAIServer视频智能分析平台未戴安全帽检测算法

随着人工智能技术的不断进步&#xff0c;CPU算法分析在视频智能分析平台中的应用日益广泛。特别是在工地安全管理领域&#xff0c;未戴安全帽检测算法已成为一项关键的安全保障措施。LiteAIServer视频智能分析平台通过结合CPU的高效运算能力和先进的深度学习算法&#xff0c;实…

两网站定时数据exchange项目详解

功能说明 A网站&#xff1a;用户可以通过表单输入嫌疑人信息&#xff0c;这些信息会被存储在内存中&#xff0c;并通过API接口返回。B网站&#xff1a;通过API接口接收从A网站同步过来的嫌疑人数据&#xff0c;并显示这些数据。主应用&#xff1a;使用APScheduler每隔1分钟从A…

【云计算】腾讯云架构高级工程师认证TCP--考纲例题,知识点总结

【云计算】腾讯云架构高级工程师认证TCCP–知识点总结&#xff0c;排版整理 文章目录 1、云计算架构概论1.1 五大版块知识点&#xff08;架构设计&#xff0c;基础服务&#xff0c;高阶技术&#xff0c;安全&#xff0c;上云&#xff09;1.2 课程详细目录1.3 云基础架构设计1.4…

sql server查看当前正在执行的sql

#统计某类sql执行次数&#xff0c;并按总体cpu消耗时间降序排序 with a as ( select er.session_id,db_name(er.database_id) as DBNAME,sy.last_batch AS 最后执行时间, er.cpu_time ,er.total_elapsed_time/1000 as sum_elapsed_time_s, CAST(csql.text AS varchar(8000)) A…

【UE5】Slider控件样式

实现根据滑柄位置确定滑条样式的功能&#xff0c;效果如下。 效果 步骤 1. 添加Slider控件和文本控件&#xff0c;其中文本控件用于显示滑条的值 2. 文本控件绑定变量&#xff0c;这里变量为“Year” 3. 当滑条的值变更后&#xff0c;设置“Year”的值&#xff0c;然后调用函…

JVM性能分析工具JProfiler的使用

一、基本概念 JProfiler&#xff1a;即“Java Profiler”&#xff0c;即“Java分析器”或“Java性能分析工具”。它是一款用于Java应用程序的性能分析和调试工具&#xff0c;主要帮助开发人员识别和解决性能瓶颈问题。 JVM&#xff1a;即“Java Virtual Machine”&#xff0c…

TongRDS 可视化连接

说明&#xff1a;TongRDS 增加了 redis 兼容接口&#xff0c;所以 redis 能连接的可视化方式&#xff0c;TongRDS 也是可以的 Redis Insight Redis Insight DataGrip DataGrip

【WPF】Prism学习(八)

Prism Dependency Injection 1.处理解析错误 1.1. 处理解析错误&#xff1a; 这个特性是在Prism 8中引入的&#xff0c;如果你的应用目标是早期版本&#xff0c;则不适用。 1.2. 异常发生的原因&#xff1a; 开发者可能会遇到多种原因导致的异常&#xff0c;常见的错误包括…

游戏引擎学习第19天

介绍 这段内容描述了开发者在进行游戏开发时&#xff0c;对于音频同步和平台层的理解和调整的过程。以下是更详细的复述&#xff1a; 开发者表达了他希望今天继续进行的工作内容。他提到&#xff0c;昨天他讲解了一些关于音频的内容&#xff0c;今天他想稍微深入讲解一下他正…

蓝队技能-应急响应篇Rookit后门进程提取网络发现隐藏技术Linux杀毒OpenArk

知识点&#xff1a; 1、应急响应-Windows-Rootkit-分析&清除 2、应急响应-Linux-Rootkit-分析&查毒&清除 内存马和rookit都是属于权限维持技术&#xff0c; 内存马一般是用来控制网站&#xff0c;rookit一般是用来控制服务器&#xff08;隐藏常规C2后门&#xff…

MAC创建一个自动操作,启动系统【睡眠】功能,并将绑定快捷键

目的 通过 Automator 创建一个服务来启动系统【睡眠】这个功能&#xff0c;并绑定快捷键。 步骤一&#xff1a;创建 Automator 服务 打开 Automator&#xff1a; ○ 在 Spotlight 中搜索 Automator&#xff0c;然后打开。选择服务类型&#xff1a; ○ 在 Automator 的启动界…

OpenLayers教程11_在OpenLayers中启用WebGL渲染

在 OpenLayers 中启用 WebGL 渲染&#xff1a;提高地图渲染性能的完整指南 目录 一、引言二、WebGL 渲染在 Web GIS 中的作用 WebGL 的优势WebGL 与 Canvas 渲染的区别 三、在 OpenLayers 中启用 WebGL 的方法四、代码实现步骤 1. 初始化地图和基本 WebGL 渲染2. 加载大规模点…

利用Matlab函数实现深度学习算法

深度学习是一种机器学习技术&#xff0c;其核心是构建多层神经网络&#xff0c;通过深入的学习来实现对数据的有效建模和分析。在深度学习的发展过程中&#xff0c;产生了许多算法和框架&#xff0c;Matlab是其中之一&#xff0c;提供了大量的深度学习函数&#xff0c;可以帮助…

每日OJ题_牛客_dd爱旋转_模拟_C++_Java

目录 牛客_dd爱旋转_模拟 题目解析 C代码 Java代码 牛客_dd爱旋转_模拟 dd爱旋转 输入描述&#xff1a; 第一行一个数n(1≤n≤1000)&#xff0c;表示矩阵大小 接下来n行&#xff0c;每行n个数&#xff0c;描述矩阵&#xff0c;其中数字范围为[1,2000] 一下来一行一个数q(1…

从零开始打造个人博客:我的网页设计之旅

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 ✨特色专栏&#xff1a…

【C语言】操作符2(含操作符的应用)

1、单目操作符 单目操作符有下面几种&#xff1a; &#xff01;、、--、&&#xff08;取地址&#xff09;、*&#xff08;指针&#xff09;、&#xff08;正号&#xff09;、-&#xff08;负号&#xff09;、~、sizeof、&#xff08;类型&#xff09; 其中就还有&和*操…

博客文章怎么设计分类与标签

首发地址&#xff08;欢迎大家访问&#xff09;&#xff1a;博客文章怎么设计分类与标签 新网站基本上算是迁移完了&#xff0c;迁移之后在写文章的过程中&#xff0c;发现个人的文章分类和标签做的太混乱了&#xff0c;分类做的像标签&#xff0c;标签也不是特别的丰富&#x…