React源码解析(1): JSX语法与react项目渲染过程
好家伙
0.前言
由于工作的需要,我不得不入手了react的全家桶,曾经我的主要技术栈是vue。
从vue转到react,一开始我感到非常不适应,jsx的语法的不了解,react hooks的使用方式,react路由的配置。。。这一度让我十分难受
但在熟悉一段时间后,我逐渐领略到react的魅力,灵活的状态管理,渲染速度,与vite集成后超快的打包速度,以及超漂亮UI组件库NextUI

(这真是我目前为止遇到的最漂亮的一套组件库,圆角,配色,动画交互)
让我们拥抱新技术吧!
1. 关于 JSX
JSX 就是“JavaScript + XML”的神奇结合。它让我们能在写 JavaScript 的同时写出类似 XML 标签的东西,看起来就像是这样:
function App() {
return (
<NextUIProvider>
<RouterProvider router={router} />
</NextUIProvider>
);
}
实际上,这些标签最后会被编译成纯 JavaScript,也就是 React 官方的说法——JSX 会被转换成 React.createElement()。
去Babel的网站试一下吧
import React from "react";
export function StudentTable() {
const students = ["panghu", "xiaofu", "daxiong", "jinxiang"];
return (
<table style={{ borderCollapse: "collapse", width: "50%", margin: "1rem auto" }}>
<thead>
<tr style={{ backgroundColor: "#f2f2f2" }}>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>序号</th>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>姓名</th>
</tr>
</thead>
<tbody>
{students.map((name, index) => (
<tr key={index}>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>{index + 1}</td>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>{name}</td>
</tr>
))}
</tbody>
</table>
);
}
Babel编译后

但用 JSX 可读性更好,写着也舒爽。
2.为什么要用jsx?
我们来看vue和react实现相同表格
React
import React from "react";
export function StudentTable() {
const students = ["panghu", "xiaofu", "daxiong", "jinxiang"];
return (
<table style={{ borderCollapse: "collapse", width: "50%", margin: "1rem auto" }}>
<thead>
<tr style={{ backgroundColor: "#f2f2f2" }}>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>序号</th>
<th style={{ border: "1px solid #ccc", padding: "8px" }}>姓名</th>
</tr>
</thead>
<tbody>
{students.map((name, index) => (
<tr key={index}>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>{index + 1}</td>
<td style={{ border: "1px solid #ccc", padding: "8px" }}>{name}</td>
</tr>
))}
</tbody>
</table>
);
}
Vue
<template>
<table style="border-collapse: collapse; width: 50%; margin: 1rem auto;">
<thead>
<tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ccc; padding: 8px;">序号</th>
<th style="border: 1px solid #ccc; padding: 8px;">姓名</th>
</tr>
</thead>
<tbody>
<tr
v-for="(student, index) in students"
:key="index"
>
<td style="border: 1px solid #ccc; padding: 8px;">{{ index + 1 }}</td>
<td style="border: 1px solid #ccc; padding: 8px;">{{ student }}</td>
</tr>
</tbody>
</table>
</template> <script>
export default {
name: "StudentTable",
data() {
return {
students: ["panghu", "xiaofu", "daxiong", "jinxiang"]
};
}
};
</script>
两段代码对比下来,你会发现
JSX语法虽然对UI进行了描述,但是,将“模板”和“逻辑”混合在一起了
且在单文件内,就可以实现多组件,还不用考虑作用域,真是太爽了!
3.react项目渲染过程
3.1.ReactElement 的数据结构
3.2.渲染流程

- 开发者使用 JSX 语法编写组件,这种语法类似于 HTML,但可以在 JavaScript 中使用。
- Babel 编译:
- Babel 是一个 JavaScript 编译器,它将 JSX 转换为 React.createElement 调用。这一步将 JSX 语法转化为 JavaScript 代码,使其可以在浏览器中运行。
3. React.createElement 调用:
- React.createElement 是一个函数,用于创建 React 元素(ReactElement)。每个 JSX 标签都会被转换为一个 React.createElement 调用。
4. ReactElement 调用:
- ReactElement 是一个轻量级的描述对象,表示界面上某个节点的结构和属性。它是构建虚拟 DOM 的基础。
5. 虚拟 DOM:
- React 使用虚拟 DOM 来描述 UI 的结构。虚拟 DOM 是 ReactElement 的集合,表示应用的当前状态。
6. ReactDOM.render():
- ReactDOM.render() 是 React 的核心方法之一。它的作用是将虚拟 DOM 渲染为真实 DOM。
- 具体过程:
- 接收虚拟 DOM 作为参数。
- 比较新旧虚拟 DOM,找出差异。
- 将差异应用到真实 DOM 上,更新界面。
- 这个过程通过高效的差异算法(Diffing Algorithm)实现,确保只更新必要的部分,从而提高性能。
7. 真实 DOM:
- 最终,经过 ReactDOM.render() 的处理,虚拟 DOM 的变化被应用到真实 DOM,用户界面得到更新。
React源码解析(1): JSX语法与react项目渲染过程的更多相关文章
- React源码解析之React.Children.map()(五)
一,React.Children是什么? 是为了处理this.props.children(this.props.children表示所有组件的子节点)这个属性提供的工具,是顶层的api之一 二,Re ...
- React源码解析:ReactElement
ReactElement算是React源码中比较简单的部分了,直接看源码: var ReactElement = function(type, key, ref, self, source, owne ...
- React源码解析-Virtual DOM解析
前言:最近一直在研究React,看了陈屹先生所著的深入React技术栈,以及自己使用了这么长时间.对React应该说有比较深的理解了,正好前阵子也把两本关于前端设计模式的书看完了,总感觉有一种知识错综 ...
- React源码解析——ReactAPI
一.API背景 api的具体转化关系 可以通过到https://babeljs.io/repl/网站去将我们创建的Jsx进行实时的转译 const React = { Children: { map, ...
- React源码解析:setState
先来几个例子热热身: ......... constructor(props){ super(props); this.state = { index: 0 } } componentDidMount ...
- React源码解析——创建更新过程
一.ReactDOM.render 创建ReactRoot,并且根据情况调用root.legacy_renderSubtreeIntoContainer或者root.render,前者是遗留的 API ...
- Android源码解析系列
转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...
- React躬行记(16)——React源码分析
React可大致分为三部分:Core.Reconciler和Renderer,在阅读源码之前,首先需要搭建测试环境,为了方便起见,本文直接采用了网友搭建好的环境,React版本是16.8.6,与最新版 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
随机推荐
- 智子: Vue Vapor年底发布alpha版本,如果有资金支持
前言 在最近的Vue Fes大会上,Vue Vapor的作者智子大佬宣布,如果能够得到资金支持,那么Vue Vapor年底就能发布alpha版本了. 关注公众号:[前端欧阳],给自己一个进阶vue的机 ...
- C++多线程应用
一个进程就是一个程序,一个程序里不止一个功能,每个功能的实现就可以交给一个线程去完成.一个进程就像是一个工程,这个工程里,有设计,有监理,有施工,就相当于三个线程,各干各的又相互配合. https:/ ...
- Tomcat弱口令上传war包
Tomcat弱口令上传war包 思路: 利用弱口令登录管理页面 ---> 部署war包 ---> getshell 环境: vulhub靶场:tomcat/tomcat8 启动 ...
- Node.js 构建命令行工具:实现 ls 命令的 -a 和 -l 选项
在日常的前端开发中,我们常常借助各种基于 Node.js 的脚手架工具来加速项目搭建和维护,比如 create-react-app 可以一键初始化一个 React 项目,eslint 则帮助我们保持代 ...
- 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-4-启动浏览器-基于Maven(详细教程)
1.简介 上一篇文章,宏哥已经在搭建的java项目环境中添加jar包实践了如何启动浏览器,今天就在基于maven项目的环境中给小伙伴们或者童鞋们演示一下如何启动浏览器. 2.eclipse中新建mav ...
- 条理清晰,浅显易懂:Lua语法技术知识详解(第三部分)
今天我们继续学习Lua语法基础教程,下篇. 9.4 函数返回值 在前面的代码中,我们实现了一个函数,输入变量a.b,函数会自动输出两个数值的和. 但是一般来说,我们的需求远远不止这些,我们可能需要一个 ...
- ARC143D Bridges
ARC143D Bridges 巧妙的图论题. 思路 分析题目,发现很像拆点. 由于拆点要设置出入点,这里我们也把 \(a_i\) 设成入点,把 \(a_i+n\) 设成出点,再次分析问题. 考虑我们 ...
- 二、STM32F103C8T6-定时器
STM32F103C8T6 定时器概述 STM32F103C8T6 作为一款广泛使用的微控制器,内置多个定时器,能够支持多种计时和控制功能,如精确延时.脉冲宽度调制(PWM).捕获比较(Capture ...
- JPEG格式研究——(2)JPEG文件格式
JPEG文件除了图像数据之外,还保存了与图片相关的各种信息,这些信息通过不同类型的TAG存储在文件中. TAG JPEG通过TAG标记压缩书记之外的信息.所有的TAG都包含一个TAG类型,TAG类型大 ...
- 用VuePress在GitHub Pages上搭建博客
请先点击链接RobinDevNotes,体验用VuePress搭建博客的效果(logo还没有合适的替换),目前部署在GitHub Pages上,国内访问速度还可以,再阅读本文感受来龙去脉和搭建过程. ...