【React进阶之路01】- JSX演变成真实DOM

article/2025/8/30 12:44:20

什么是 JSX

JSX 是 ECMAScript 一个类似 XML 的语法扩展。基本上,它只是为 React.createElement() 函数提供语法糖,从而让在我们在 JavaScript 中,使用类 HTML 模板的语法,进行页面描述。

JSX编译(babel)

由于JSX是javascript的一种扩展,所以这就直接决定了浏览器不能像天然支持js一样支持jsx,所以jsx需要被编译后才能被识别,这个编译工作正是由Babel来实现的

我们先来看个简单的JSX demo,看看经过babel的编译他会变成什么?
在这里插入图片描述
上图可看出,jsx中的每个标签都会被编译为React.crerateElement函数调用,接下来我们就要结合源码看下这个React.crerateElement函数

createElement源码

export function createElement(type, config, children) {let propName;  // 用来存储后面需要用到的元素属性const props = {};  // 用来存储元素属性的键值对集合// 以下4个属性都是React元素的属性,暂时不用管let key = null;let ref = null;let self = null;let source = null;// config对象是传入的元素的属性if (config != null) {// 进来第一件事是依次对上述4个属性赋值if (hasValidRef(config)) {ref = config.ref;if (__DEV__) {warnIfStringRefCannotBeAutoConverted(config);}}// 此处将key值字符串化if (hasValidKey(config)) {if (__DEV__) {checkKeyStringCoercion(config.key);}key = '' + config.key;}self = config.__self === undefined ? null : config.__self;source = config.__source === undefined ? null : config.__source;// 接着就是把config里的属性一个个地搬到props对象中(前面定义的) for (propName in config) {if (// 筛选出可以提进props对象里的属性hasOwnProperty.call(config, propName) &&!RESERVED_PROPS.hasOwnProperty(propName)) {props[propName] = config[propName];}}}// childrenLength为当前元素的子元素个数,减去2是type和config占用的长度const childrenLength = arguments.length - 2;if (childrenLength === 1) {  // 文本节点props.children = children;} else if (childrenLength > 1) {const childArray = Array(childrenLength);for (let i = 0; i < childrenLength; i++) {childArray[i] = arguments[i + 2];}if (__DEV__) {if (Object.freeze) {Object.freeze(childArray);}}props.children = childArray;}// 处理defaultPropsif (type && type.defaultProps) {const defaultProps = type.defaultProps;for (propName in defaultProps) {if (props[propName] === undefined) {props[propName] = defaultProps[propName];}}}if (__DEV__) {if (key || ref) {const displayName =typeof type === 'function'? type.displayName || type.name || 'Unknown': type;if (key) {defineKeyPropWarningGetter(props, displayName);}if (ref) {defineRefPropWarningGetter(props, displayName);}}}// 最后调动ReactElement方法,传入刚处理的参数return ReactElement(type,key,ref,self,source,ReactCurrentOwner.current,props,);
}

createElement方法接受3个参数

type: 用于标识节点的类型,比如‘div’、'span’等
config:以对象形式传入,组件所有的属性都会以键值对的形式存储在config对象中
children:以对象形式传入,他记录的是组件标签之间嵌套的内容

我们根据上述代码可以将createElement 函数进行拆解:在这里插入图片描述
createElement 每一步基本都是在格式化数据,说白点就是它更像是开发者和ReactElement函数调用之间的参数中介,它接受较为简单的参数,然后按照ReactElement函数入参的预期对参数进行相应的格式化,然后最终通过调用ReactElement函数来实现元素的创建 ,所以接下来我们重点来看下ReactElement函数内部源码

ReactElement源码:

const ReactElement = function(type, key, ref, self, source, owner, props) {const element = {$$typeof: REACT_ELEMENT_TYPE, // 它是一个常量,用来标识该对象是一个ReactElement// 内置属性赋值type: type,key: key,ref: ref,props: props,// 记录创造该元素的组件_owner: owner,};if (__DEV__) {   // 这里是对__DEV__环境下的处理,对逻辑理解没什么影响,可以先不看element._store = {};Object.defineProperty(element._store, 'validated', {configurable: false,enumerable: false,writable: true,value: false,});Object.defineProperty(element, '_self', {configurable: false,enumerable: false,writable: false,value: self,});Object.defineProperty(element, '_source', {configurable: false,enumerable: false,writable: false,value: source,});if (Object.freeze) {Object.freeze(element.props);Object.freeze(element);}}return element;
};

所以从上面源码中可以看出,ReactElement函数也是很简单的,它只是对参数进行了组装,组装成了element对象返回,其实这里说的element对象就是我们常提到的虚拟DOM,我们可以打印一个出来看看:

function App() {const element =(<div className="App">hello jsx</div>);console.log(element,'element')return element;
}export default App;

在这里插入图片描述
没错,上面的就是虚拟DOM,它就长这个吊样,那么它是怎么变成最终的真实DOM的呢?

此时不少同学应该已经能猜到了,没错就是ReactDOM.render方法

ReactDOM.render简单实现:

// 传入两个参数,虚拟dom, 应用容器
function render(vDom, container) {let dom;// 判断当前的节点是文本还是对象if (vDom.type === 'TEXT') {dom = document.createTextNode(vDom.props.nodeValue);} else {// 当前节点是一个对象dom = document.createElement(vDom.type);}// 虚拟 dom 的属性,将 vDom 的除了 children 的属性都挂在到 dom 对象上if (vDom.props) {Object.keys(vDom.props)// 过滤掉了 children 属性.filter(key => key !== 'children')// 循环剩余所有属性添加到dom上.forEach(item => {dom[item] = vDom.props[item];});}// 通过递归调用实现子元素if (vDom.props && vDom.props.children && vDom.props.children.length > 0) {vDom.props.children.forEach(child => {render(child, dom);});}container.appendChild(dom);
}const ReactDOM = {render,
};export default ReactDOM;

至此,从开始的JSX就转换成了真实的DOM节点了,整天流程梳理后如下:
在这里插入图片描述


http://chatgpt.dhexx.cn/article/35MAvucA.shtml

相关文章

JStorm—实时流式计算框架入门介绍

JStorm介绍 JStorm是参考storm基于Java语言重写的实时流式计算系统框架&#xff0c;做了很多改进。如解决了之前的Storm nimbus节点的单点问题。   JStorm类似于Hadoop MapReduce系统&#xff0c;用户按照指定的接口去实现一个任务&#xff0c;任务提交给JStorm进行运行&…

jstorm基本概念

基本概念 longdafeng edited this page on 29 Sep 4 revisions Pages 69 0.7.1 changelist0.9.0 change list0.9.0 性能测试0.9.1_change_list0.9.2_change_list0.9.3_change_listAck 机制Acking Framework ImplementationApplication examplesBasic conceptionBuild JStormD…

ReactJS入门之Model层

目录 一&#xff1a;分层 二&#xff1a;使用DVA进行数据分层管理 三&#xff1a;在model中请求数据 四&#xff1a;mock数据 一&#xff1a;分层 上图中&#xff0c;左侧是服务端代码的层次结构&#xff0c;由 Controller 、 Service 、 Data Access 三层组成服务端系统…

初识Jstorm 多个bolt应用

最近接到任务说要使用jstorm处理业务&#xff0c;之前没接触过&#xff0c;只能硬着头皮来&#xff0c;接下来谈谈我这两天的收获 1&#xff0c;怎么了解jstorm&#xff0c;这个答案没什么固定的&#xff0c;但是我个人比较喜欢去看官方的文档&#xff0c;如果官方的文档实在找…

大数据(十五) - JStorm

JStorm 是一个分布式实时计算引擎&#xff0c;是淘宝开源的 随着Storm 的规模越来越大&#xff0c;发现原有的很多Storm设计&#xff0c;只能适合小集群中运行&#xff0c;当集群规模超过100台时&#xff0c;均会出现一些或这或那的问题。JStorm 比Storm更稳定&#xff0c;更强…

初识JavaScript---(1)

初识JavaScript———&#xff08;1&#xff09;&#xff01;&#xff01;&#xff01; 一、初识JavaScript 1.什么是JavaScript&#xff1f; JavaScript是运行在浏览器上的脚本语言&#xff0c;简称JS。JavaScript程序不需要我们程序员手动编译&#xff0c;编写完源代码之后…

【JavaScript高级进阶】构造函数和原型,学会prototype

目录 前言 1.构造函数和原型 1.1使用prototype解决内存浪费的问题 1.2constructor构造函数构造器构造函数 2.原型链 2.1js中成员查找规则 2.2原型对象this指向 2.3扩展内置对象 3.call作用 4.继承 4.1利用原型对象继承 写在最后 前言 哈喽哈喽大家好&#xff0c;因为…

Jstorm 基本概念

本质 基于消息的流水线处理模型是一套类似MapReduce一样的编程模型内核是一套调度系统 适合的业务 高并发的计算任务数据流之间相互无依赖 编程模型 Topology&#xff1a;即一个数据流的拓扑结构&#xff0c;包含多个Spout和BoltSpout&#xff1a;从外部获取数据&#xff…

JStorm和Storm比较

1、What——JStorm是什么&#xff1f;  概述&#xff1a; JStorm 是一个分布式实时计算引擎&#xff0c;类似Hadoop MapReduce的系统&#xff0c; 用户按照规定的编程规范实现一个任务&#xff0c;然后将这个任务递交给JStorm系统&#xff0c;Jstorm将这个任务跑起来&#xf…

JStorm Storm 上手demo

折线之间的内容整理自&#xff1a; http://blog.csdn.net/suifeng3051/article/details/38369689 -------------------------------------------------------------------------------------------------------------------------------------------- 在全面介绍Storm之前&…

PyTorch从零开始实现Transformer

文章目录 自注意力Transformer块编码器解码器块解码器整个Transformer参考来源全部代码&#xff08;可直接运行&#xff09; 自注意力 计算公式 代码实现 class SelfAttention(nn.Module):def __init__(self, embed_size, heads):super(SelfAttention, self).__init__()self.e…

jstorm storm 入门demo

jstorm和storm比较 jstorm 是阿里巴巴开源的基于storm采用Java重写的一套分布式实时流计算框架&#xff0c;使用简单&#xff0c;特点如下&#xff1a; 1&#xff0c;开发非常迅速: 接口简单&#xff0c;容易上手&#xff0c;只要遵守Topology&#xff0c;Spout&#xff0c;Bo…

JStorm介绍

一、简介 JStorm是一个分布式实时计算引擎。JStorm是一个类似于Hadoop MapReduce的系统&#xff0c;用户按照指定的接口实现一个任务&#xff0c;然后将这个任务交给JStorm系统&#xff0c;JStorm将这个任务跑起来&#xff0c;并按7*24小时运行。如果中间一个worker发生了意外…

马氏距离实例详解

介绍 马氏距离是由印度统计学家马哈拉诺比斯&#xff08;P. C. Mahalanobis&#xff09;提出的&#xff0c;表示数据的协方差距离。它是一种有效的计算两个未知样本集的相似度的方法。与欧氏距离不同的是它考虑到各种特性之间的联系&#xff08;例如&#xff1a;一条关于身高的…

距离度量:闵氏、欧式、马氏、余弦、汉明等

目录 1. 闵氏距离&#xff08;Minkowski Distance&#xff09; 2. 欧式距离&#xff08;Euclidean Distance&#xff09; 3. 标准化欧式距离&#xff08;Standardized Euclidean distance&#xff09; 4. 马氏距离&#xff08;Mahalanobis Distance&#xff09; 5. 余弦距…

马氏距离(Mahalanobis Distance)推导及几何意义

看了一些博客对马氏距离的解释&#xff0c;似乎没有讲到本质的地方&#xff0c;本文从欧氏距离存在的问题开始入手&#xff0c;一步步推导出马氏距离&#xff0c;并得出结论&#xff1a;原始空间中的马氏距离等于坐标旋转变换及缩放后的空间中的欧氏距离。 假设数据集 X ∈ R N…

直观理解--马氏距离

首先我们很了解欧氏距离了&#xff0c;就是用来计算欧式空间&#xff08;就是我们常见的坐标系&#xff09;中两个点的距离的。 比如点 x ( x 1 , … , x n ) x (x_1,…,x_n) x(x1​,…,xn​) 和 y ( y 1 , … , y n ) y (y_1,…,y_n) y(y1​,…,yn​) 的欧氏距离为&…

Mahalanobis距离(马氏距离)的“哲学”解释

讲解教授&#xff1a;赵辉 (FROM : UESTC) 课程&#xff1a;《模式识别》 整理&#xff1a;PO主 基础知识&#xff1a; 假设空间中两点x&#xff0c;y&#xff0c;定义&#xff1a; 欧几里得距离&#xff0c; Mahalanobis距离&#xff0c; 不难发现&#xff0c;如果去掉…

六大距离:欧式距离、街道距离、马氏距离等

文章目录 1 简 介2 距离特征2.1 Euclidean距离2.2 Cosine距离2.3 manhattan距离2.4 chebyshev距离2.5 minkowski距离2.6 mahalanobis距离 3 代 码实现 1 简 介 数值向量是数据建模问题中最为常见的一类特征&#xff0c;例如&#xff1a; 在一些涉及图片&#xff0c;文本信息等…

马氏距离例题详解(全网最详细)

马氏距离例题详解 定义 马哈拉诺比斯距离是由印度统计学家马哈拉诺比斯 (英语)提出的&#xff0c;表示数据的协方差距离。它是一种有效的计算两个未知样本集的相似度的方法。与欧氏距离不同的是它考虑到各种特性之间的联系&#xff08;例如&#xff1a;一条关于身高的信息会带…