当前位置: 首页 > news >正文

React 原理篇 - 深入理解虚拟 DOM

一、什么是虚拟 DOM?

在前端开发中,“虚拟 DOM” 是一个高频出现的术语,尤其在 React 生态中被广泛讨论。但很多开发者对它的理解往往停留在 “JS 对象” 这个表层认知上。

实际上,虚拟 DOM 是一种编程概念—— 在这个概念里,UI 以一种理想化的、“虚拟的” 表现形式被保存于内存中。它本质上是对真实 DOM 的一种描述,而不是具体的实现。

React 官方文档对虚拟 DOM 的定义是:“一种编程概念,UI 以一种理想化的,或者说 ’ 虚拟的 ’ 表现形式被保存于内存中”。这意味着,只要能描述真实 DOM 的层次结构,无论采用何种形式(JSON、XML 等),都可以称为虚拟 DOM。而 React 选择了JS 对象作为这种思想的具体实现。

二、为什么需要虚拟 DOM?

在深入了解虚拟 DOM 的工作原理前,我们先思考一个问题:为什么需要虚拟 DOM?它解决了什么痛点?

2.1 性能优化:减少 DOM 操作成本

浏览器操作 DOM 的成本非常高,主要原因有两点:

  • DOM 对象包含大量属性和方法(远多于普通 JS 对象)
  • DOM 操作会触发浏览器的重排(Reflow)和重绘(Repaint)

相比之下,JS 层面的计算成本要低得多。通过先在 JS 层面对虚拟 DOM 进行计算和比对,再映射到真实 DOM,可以大幅减少不必要的 DOM 操作。

虚拟 DOM 的优势在更新阶段尤为明显 —— 它避免了全量销毁重建 DOM 的昂贵操作,只做必要的修改。

2.2 跨平台渲染能力

虚拟 DOM 最大的价值之一是提供了平台无关性。它将 UI 描述与具体渲染逻辑分离,使得同一套代码可以在不同平台渲染:

  • 浏览器环境:通过 ReactDOM 渲染为 DOM
  • 移动设备:通过 React Native 渲染为原生组件
  • 服务端:通过 ReactDOMServer 渲染为字符串
  • 测试环境:直接渲染为 JS 对象进行断言

这种抽象能力完美契合了 “一次编写,多端运行” 的现代开发需求。

三、React 中的虚拟 DOM 实现

在 React 中,虚拟 DOM 以 “React 元素” 的形式存在。让我们从 JSX 开始,一步步揭开它的面纱。

3.1 JSX 与 createElement 的关系

我们编写的 JSX 代码:

<h1 className="title" id="header">Hello, Virtual DOM!<span>React</span>
</h1>

会被 Babel 编译为 createElement 方法的调用:

React.createElement('h1',{ className: 'title', id: 'header' },'Hello, Virtual DOM!',React.createElement('span', null, 'React')
)

这个方法最终会返回一个描述 DOM 结构的 JS 对象 —— 这就是 React 中的虚拟 DOM:

{$$typeof: Symbol(react.element),type: 'h1',key: null,ref: null,props: {className: 'title',id: 'header',children: ['Hello, Virtual DOM!',{$$typeof: Symbol(react.element),type: 'span',// ... 其他属性}]},_owner: null
}

3.2 createElement 核心逻辑解析

React 的 createElement 函数主要做了四件事:

  1. 处理属性(过滤保留字、提取 key 和 ref)
  2. 处理子元素(支持多个子节点,转为数组)
  3. 合并默认属性(defaultProps)
  4. 创建并返回 React 元素对象

简化版实现如下:

function createElement(type, config, children) {const props = {};let key = null;let ref = null;// 处理配置属性if (config) {key = config.key || null;ref = config.ref || null;// 复制非保留字属性到 propsfor (const prop in config) {if (config.hasOwnProperty(prop) && !RESERVED_PROPS.hasOwnProperty(prop)) {props[prop] = config[prop];}}}// 处理子元素const childrenLength = arguments.length - 2;if (childrenLength === 1) {props.children = children;} else if (childrenLength > 1) {props.children = Array.from(arguments).slice(2);}// 合并默认属性if (type && type.defaultProps) {for (const prop in type.defaultProps) {if (props[prop] === undefined) {props[prop] = type.defaultProps[prop];}}}return {$$typeof: REACT_ELEMENT_TYPE,type,key,ref,props,_owner: null};
}

这个对象包含了渲染真实 DOM 所需的全部信息:元素类型(type)、属性(props)、子元素(children)等。

四、虚拟 DOM 的工作流程

虚拟 DOM 不是孤立存在的,它是 React 渲染流程的核心环节。完整流程包括:

4.1 初始渲染

  • 从 JSX 生成虚拟 DOM
  • 将虚拟 DOM 转换为真实 DOM 并插入页面

4.2 状态更新

  • 状态变化触发重新渲染,生成新的虚拟 DOM
  • 通过 Diff 算法对比新旧虚拟 DOM,找出差异
  • 只将差异部分应用到真实 DOM(Patch 过程)

4.3 Diff 算法:高效比对的核心

React 的 Diff 算法是虚拟 DOM 实现高性能的关键,它基于三个假设:

  • 不同类型的元素会产生不同的树
  • 可以通过 key 属性标识同一层级的子元素,保持稳定性
  • 只进行同层级比对(时间复杂度 O (n))

这种策略大幅简化了比对过程,同时保证了大多数场景下的高效性。

五、虚拟 DOM 的局限性

尽管虚拟 DOM 带来了诸多好处,但也存在一定问题:

  1. 初始渲染开销:首次渲染时,虚拟 DOM 因为多了一层 JS 计算,可能比直接操作 DOM 稍慢
  2. 过度优化:对于简单场景,手动优化的 DOM 操作可能比虚拟 DOM 更高效
  3. 内存占用:大量虚拟 DOM 对象可能占用较多内存

React 团队也在不断优化这些问题,例如通过 Fiber 架构实现增量渲染,进一步提升性能。

六、总结

虚拟 DOM 是 React 架构的基石,它通过 “描述式编程” 的思想,让开发者专注于 UI 应该是什么样子,而不是如何操作 DOM。

核心要点:

  • 虚拟 DOM 是一种思想,JS 对象是 React 中的实现方式
  • 主要优势是减少 DOM 操作和提供跨平台能力
  • 工作流程包括:创建虚拟 DOM → 比对差异 → 应用差异
  • React 通过 createElement 方法将 JSX 转换为虚拟 DOM 对象

文章转载自:

http://TrOFlWI1.mqnbm.cn
http://0OCXw7Kg.mqnbm.cn
http://7h0xJtR4.mqnbm.cn
http://tkWkX5qV.mqnbm.cn
http://ELqy0ozH.mqnbm.cn
http://KZTAe7eC.mqnbm.cn
http://dB0zE8pF.mqnbm.cn
http://MRcBwQKH.mqnbm.cn
http://neiQYpcL.mqnbm.cn
http://a6OnLcHN.mqnbm.cn
http://CUmCEy4h.mqnbm.cn
http://Jt5cJjIL.mqnbm.cn
http://h1N9lbJm.mqnbm.cn
http://4qRRXONc.mqnbm.cn
http://G1BJry0r.mqnbm.cn
http://Jdvzu2CT.mqnbm.cn
http://pAxThBOF.mqnbm.cn
http://b0i5dMCO.mqnbm.cn
http://GmxwaqRI.mqnbm.cn
http://Ezt51RTd.mqnbm.cn
http://pg7L74hu.mqnbm.cn
http://Mm2L79Tz.mqnbm.cn
http://l0fpBT6J.mqnbm.cn
http://hon3a1Lp.mqnbm.cn
http://yvMWXWz3.mqnbm.cn
http://EuThysft.mqnbm.cn
http://ZNmyS3rK.mqnbm.cn
http://2EiVWBTG.mqnbm.cn
http://nSjZQafK.mqnbm.cn
http://xIAVutOY.mqnbm.cn
http://www.dtcms.com/a/381370.html

相关文章:

  • [能源化工] 面向锂电池RUL预测的开源项目全景速览
  • 分布式专题——10.5 ShardingSphere的CosID主键生成框架
  • 【Redis#9】其他数据结构
  • C++使用拉玛努金公式计算π的值
  • 上海市2025CSP-J十连测Round 5卷后感
  • RDB/AOF------Redis两大持久化方法
  • 【图解】idea中快速查找maven冲突
  • Dubbo SPI机制
  • 《Linux 基础指令实战:新手入门的命令行操作核心教程(第一篇)》
  • 【开题答辩全过程】以 “饭否”食材搭配指南小程序的设计与实现为例,包含答辩的问题和答案
  • RabbitMQ 在实际开发中的应用场景与实现方案
  • 有没有什么办法能批量去除很多个PDF文件的水印
  • JavaScript 内存管理与常见泄漏排查(闭包、DOM 引用、定时器、全局变量)
  • ArkAnalyzer源码初步分析I——分析ts项目流程
  • Linux_基础指令(二)
  • 什么是子网?
  • 【前端】【utils】高效文件下载技术解析
  • FastAPI 中内省函数 inspect.signature() 作用
  • 【Linux】Linux进程概念(上)
  • 前端vue使用canvas封装图片标注功能,鼠标画矩形框,标注文字 包含下载标注之后的图片
  • 水库运行综合管理平台
  • langgraph astream使用详解
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(31):文法運用第9回3+(考え方11)
  • shell脚本练习:文件检查与拷贝
  • 书籍成长书籍文字#创业付费杂志《财新周刊》2025最新合集 更33期
  • 《AI游戏开发中的隐性困境:从战斗策略失效到音效错位的深度破局》
  • UVM寄存器模型与通道机制
  • 一个简单的GPU压力测试脚本-python版
  • Linux x86 stability和coredump
  • Claude-Flow AI协同开发:从“CTO”到“人机共生体”的AI协同开发