【 React 】React JSX 转换成真实DOM的过程?
1. 是什么
react通过将组件编写的JSX映射到屏幕,以及组件中的状态发生了变化之后React会将这些「变化」更新到屏幕上
在前面文章了解中,JSX通过babel最终转化成React.createElement这种形式,例如:
<div>< img src="avatar.png" className="profile" /><Hello />
</div>
会被babel 转换成如下:
React.createElement("div",null,React.createElement("img", {src: "avatar.png",className: "profile"}),React.createElement(Hello, null)
);
在转化过程中,babel在编译时会判断JSX中组件的首字母:
- 当首字母为小写时,其被认定为原生DOM标签,createElement的第一个变量被编译为字符串
- 当首字母为大写时,其被认定为自定义组件,createElement的第一个变量被编译为对象
最终都会通过RenderDOM.render(…)方法进行挂载,如下:
ReactDOM.render(<App />, document.getElementById("root"));
2. 过程
在react中,节点大致可以分成四个类别:
- 原生标签节点
- 文本节点
- 函数组件
- 类组件
如下所示:
class ClassComponent extends Component {static defaultProps = {color: "pink"};render() {return ( <div className="border"> <h3>ClassComponent</h3> <p className={this.props.color}>{this.props.name}</p ></div> ); }
}
function FunctionComponent(props) {return ( <div className="border">FunctionComponent<p>{props.name}</p ></div> );
}
const jsx = ( <div className="border"><p>xx</p > < a href=" ">xxx</ a> <FunctionComponent name=" " /><ClassComponent name=" " color="red" /></div>
);
这些类别最终都会被转化成React.createElement这种形式
React.createElement其被调用时会传入标签类型type,标签属性props及若干子元素children ,作用是生成一个虚拟Dom对象,如下所示:
function createElement(type, config, ...children) {if (config) {delete config.__self;delete config.__source; }//源码中做了详细处理,比如过滤掉 ! key ref等const props = {...config,children: children.map(child =>typeof child === "object" ? child : createTextNode(child) ) };return {type,props};
}
function createTextNode(text) {return {type: TEXT,props: {children: [],nodeValue: text} };
}
export default {createElement
};
createElement会根据传入的节点信息进行一个判断:
- 如果是原生标签节点,type是字符串,如div、span
- 如果是文本节点,type就没有,这里是TEXT
- 如果是函数组件,type是函数名
- 如果是类组件,type是类名
虚拟DOM会通过ReactDOM.render进行渲染成真实DOM,使用方法如下:
ReactDOM.render(element,container[,callback])
当首次调用时,容器节点里的所有DOM元素都会被替换,后续的调用则会使用React的diff算法进行高效的更新
如果提供了可选的回调函数callback ,该回调将在组件被渲染或更新之后被执行render大致实
现方法如下:
function render(vnode, container) {console.log("vnode", vnode); //虚拟 DOM 对象// vnode _> nodeconst node = createNode(vnode, container);container.appendChild(node);
}// 创建真实DOM节点
function createNode(vnode, parentNode) {let node = null;const {type, props} = vnode;if (type === TEXT) {node = document.createTextNode("");} else if (typeof type === "string") {node = document.createElement(type); } else if (typeof type === "function") {node = type.isReactComponent? updateClassComponent(vnode, parentNode) : updateFunctionComponent(vnode, parentNode); } else {node = document.createDocumentFragment(); }reconcileChildren(props.children, node);updateNode(node, props);return node;}//遍历下子 vnode 然后把子vnode-> 真实DOM 再插入到父node中
function reconcileChildren(children, node) {for (let i = 0; i < children.length; i++) {let child = children[i];if (Array.isArray(child)) {for (let j = 0; j < child.length; j++) {render(child[j], node); } } else {render(child, node); } }
}
function updateNode(node, nextVal) {Object.keys(nextVal) .filter(k => k !== "children") .forEach(k => {if (k.slice(0, 2) === "on") { node.addEventListener(eventName, nextVal[k]); } else {node[k] = nextVal[k]; } });
}
//返回真实 dom节点
// 执行函数
function updateFunctionComponent(vnode, parentNode) {const {type, props} = vnode;let vvnode = type(props);const node = createNode(vvnode, parentNode);return node;
}// dom// 先实例化,再执行render函数
function updateClassComponent(vnode, parentNode) {const {type, props} = vnode;let cmp = new type(props);const vvnode = cmp.render();const node = createNode(vvnode, parentNode);return node;
}
export default {render
};
3. 总结
渲染流程如下所示:
- 使用React.createElement或JSX编写React组件,实际上所有的JSX代码最后都会转换成React.createElement(…),Babel帮助我们完成了这个转换的过程。
- createElement函数对key和ref等特殊的props进行处理,并获取defaultProps对默认props进行赋值,并且对传入的孩子节点进行处理,最终构造成一个虚拟DOM对象
- ReactDOM.render将生成好的虚拟DOM渲染到指定容器上,其中采用了批处理、事务等机制并且对特定浏览器进行了性能优化,最终转换为真实DOM
相关文章:
【 React 】React JSX 转换成真实DOM的过程?
1. 是什么 react通过将组件编写的JSX映射到屏幕,以及组件中的状态发生了变化之后React会将这些「变化」更新到屏幕上 在前面文章了解中,JSX通过babel最终转化成React.createElement这种形式,例如: <div>< img src"…...
[Open3d]: 知识记录
python api 官方手册:http://www.open3d.org/docs/release/ 可视化:http://www.open3d.org/docs/release/tutorial/visualization/visualization.html python-vis 参考代码:https://github.com/isl-org/Open3D/tree/master/examples/python/v…...
css面试题
1、css盒模型 a、标准盒模型---在标准盒模型中,width的宽度指的是content的宽度 b、怪异盒模型---在怪异盒模型中,width的宽度等于contentborderpadding 切换盒子模型的话,使用box-sizing。 2、link和import的区别 a、link是html标签&#x…...
vscode调试launch.json常用格式
1、简单的模版 定义一个简单的模版如下: {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid830387"version": "0.2.0","configuration…...
巨细!Python爬虫详解
爬虫(又称为网页蜘蛛,网络机器人,在 FOAF 社区中间,更经常的称为网页追逐者);它是一种按照一定的规则,自动地抓取网络信息的程序或者脚本。 如果我们把互联网比作一张大的蜘蛛网,那…...
项目中如何进行限流(限流的算法、实现方法详解)
❤ 作者主页:李奕赫揍小邰的博客 ❀ 个人介绍:大家好,我是李奕赫!( ̄▽ ̄)~* 🍊 记得点赞、收藏、评论⭐️⭐️⭐️ 📣 认真学习!!!🎉🎉 文章目录 限流的算法漏…...
https在win7的环境下如何配置
https在win7的环境下如何配置?在Windows7环境下配置https,需要完成以下步骤: 1)安装Web服务器软件 可以选择安装常用的Web服务器软件,如Apache、Nginx或IIS,这些服务器软件都支持https。 2)获…...
Day69:WEB攻防-Java安全JWT攻防Swagger自动化算法签名密匙Druid泄漏
目录 Java安全-Druid监控-未授权访问&信息泄漏 黑盒发现 白盒发现 攻击点 Java安全-Swagger接口-导入&联动批量测试 黑盒发现 白盒发现 自动化发包测试 自动化漏洞测试 Java安全-JWT令牌-空算法&未签名&密匙提取 识别 JWT 方式一:人工识…...
Python Windows系统 虚拟环境使用
目录 1、安装 2、激活 3、停止 1、安装 1)为项目新建一个目录(比如:目录命名为learning_log) 2)在终端中切换到这个目录 3)执行命令:python -m venv ll_env,即可创建一个名为ll…...
栈和队列的学习
存储方式分两类:顺序存储和链式存储 栈:只允许从一端进行数据插入和删除的线性表:先进后出 FILO 队列:只允许从一端进行数据插入,另一端进行数据删除的线性表:先进先出 FIFO 栈 创建空栈,创建…...
【机器学习】基于机器学习的分类算法对比实验
摘要 基于机器学习的分类算法对比实验 本论文旨在对常见的分类算法进行综合比较和评估,并探索它们在机器学习分类领域的应用。实验结果显示,随机森林模型在CIFAR-10数据集上的精确度为0.4654,CatBoost模型为0.4916,XGBoost模型为…...
民航电子数据库:mysql与cae建表语法差异
目录 一、场景二、语法差异 一、场景 1、使用CAEMigrator-1.0.exe将mysql数据库迁移至cae数据库时,迁移速度非常慢,而且容易卡死(可能是部署cae数据库的服务器资源不足导致) 2、所以将mysql数据库导出为sql脚本,通过…...
(学习日记)2024.03.15:UCOSIII第十七节:任务的挂起和恢复
写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…...
聚类分析 | Matlab实现基于NNMF+DBO+K-Medoids的数据聚类可视化
聚类分析 | Matlab实现基于NNMFDBOK-Medoids的数据聚类可视化 目录 聚类分析 | Matlab实现基于NNMFDBOK-Medoids的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 NNMFDBOK-Medoids聚类,蜣螂优化算法DBO优化K-Medoids 非负矩阵分解(…...
Unity类银河恶魔城学习记录11-3 p105 Inventory UI源代码
Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_itemSlot.cs using System.Collections; using System.Collections.Gen…...
Vue3 + Vite + ts引入本地图片
Vue3 Vite ts引入本地图片 单张图片导入 单个图片导入,不过多阐述,通过 import 导入需要使用的图片。 import imgName from /assets/img/imgName.png 多张图片导入 new URL() import.meta.url import.meta.url 是一个 ESM 的原生功能࿰…...
图斑或者道路如何单独显示名称在图斑上或者道路上
0序: 遇到过多个测绘、工程、林业相关业务的客户,在加载一些图斑数据,线路数据时,希望能够单独的把图斑的名称,显示到图斑上,或者路网上面。 之前多数推荐的办法: 1.shp可以直接在图新地球中…...
docker 修改默认存储位置
一般系统下系统盘可能磁盘空间有限,需要将docker的存储目录改到其他位置 docker info 查看docker的版本 低版本docker在配置json中增加"graph":"/var/lib/docker" 高版本docker在配置json中增加"data-root":"/var/lib/docker&q…...
Springboot+vue的医疗挂号管理系统+数据库+报告+免费远程调试
效果介绍: Springbootvue的医疗挂号管理系统,Javaee项目,springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的医疗挂号管理系统,采用M(model)V(view)C(con…...
【Effective C++】39 明智而审慎地使用private继承
在之前论证过c如何将public 继承视为 is-a 关系。在哪个例子里,class Student 以 public 形式继承class Person, 于是编译器在必要时刻将Students暗自转化为Person.如果此时我们以 private 继承替换 public继承。 class Person {...}; class Student: p…...
除了排错,你可能不知道OPC Expert v8.1还能做这些:数据归档、计算与冗余实战
解锁OPC Expert v8.1的隐藏潜力:数据归档、实时计算与冗余架构实战指南在工业自动化领域,OPC Expert常被视为故障排查的"急救箱",但它的能力远不止于此。当大多数工程师还在用它解决DCOM配置问题时,少数先行者已经用它重…...
浏览器 Profile 环境排查:Cookie、LocalStorage、网络出口与自动化任务配置清单
一、为什么浏览器环境经常“今天能用,明天失效”很多团队遇到登录状态丢失、页面配置异常、自动化任务失败时,会先怀疑网络、脚本或系统本身。但在实际项目里,问题经常不是单点故障,而是浏览器环境缺少稳定管理:对象常…...
基于声卡与电流互感器的安全交流功率测量系统设计与实践
1. 项目概述:用声卡安全测量交流功率我一直对各种测量技术抱有浓厚的兴趣,毕竟“测量即认知”这句老话在今天依然适用。对于电力消耗和产出,没有什么比直接测量更能说明问题了。交流功率的测量,核心在于同时获取电压和电流的瞬时值…...
为内部知识库问答机器人接入Taotoken多模型增强回答效果
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为内部知识库问答机器人接入Taotoken多模型增强回答效果 构建一个高效的企业内部知识库问答机器人,核心挑战在于如何让…...
2026年LLM推理加速全景:量化、投机解码与KV Cache工程实战
大语言模型推理速度慢、成本高,是阻碍AI大规模落地的核心障碍之一。一个7B参数的模型,在标准配置下每秒只能生成约30个token,对于需要实时响应的应用来说几乎无法接受。但2026年,一系列推理加速技术的成熟,让这一局面发…...
中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程
中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 掌握中兴光猫的设备管理和权限获取能力是网络管理员和技术爱好者…...
CANoe诊断测试没CDD文件怎么办?手把手教你用Fault Memory窗口和CAPL脚本读取解析DTC故障码
CANoe诊断测试无CDD文件的实战解决方案:从Fault Memory到CAPL脚本全解析当CDD文件缺失或定义不清晰时,诊断测试工程师常常陷入困境。本文将深入探讨如何利用Fault Memory窗口的基础功能,并通过CAPL脚本实现更灵活、更强大的故障码读取与解析方…...
AI IDE 革命:程序员正在被重新定义
很多开发者第一次使用 Cursor 的 CtrlK 或 Composer(高级多文件编辑模式)时,都会有一种强烈的、甚至让人有些脊背发凉的冲击感。 因为: 它已经不再是那个我们熟悉的、只能在原地等待光标落下的: “代码自动补全插件&am…...
【python】ImportError: DLL load failed while importing QtWidgets: 找不到指定的程序。重新安装后搞定
文章目录前言一、PyQt6引用后报错二、使用步骤总结前言 想做个好看的界面,引用了PyQt6,却产生了新问题。 pip install pyqt6-tools,优先做这个动作进行修复。 一、PyQt6引用后报错 python里引用: from PyQt6.QtWidgets import…...
DeepSeek模型微调全链路解析:从数据准备、LoRA配置到推理部署的7大关键步骤
更多请点击: https://intelliparadigm.com 第一章:DeepSeek模型微调全链路概览 DeepSeek系列大语言模型(如DeepSeek-V2、DeepSeek-Coder)凭借其开源特性、高性能推理能力与丰富的领域适配性,已成为工业界与学术界微调…...
