好家伙

 

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的网站试一下吧

https://babeljs.io/repl

一个简单的表格
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进行了描述,但是,将“模板”和“逻辑”混合在一起了

 

在 JSX 中,你需要使用 JavaScript 的表达式(如变量、条件判断、循环等)直接对 UI 进行描述,类似于“模板 + 逻辑”的混合写法,具有较高的灵活度和可组合性。
 
刚开始时,我:jsx,真不行,一坨
两周后,我:这jsx哪里不行了,这jsx太棒了!
 
清晰的组件功能结构,以及动态生成UI无不让我觉得react写起来真是非常爽!

且在单文件内,就可以实现多组件,还不用考虑作用域,真是太爽了!

 

 

3.react项目渲染过程

3.1.ReactElement 的数据结构

虚拟 DOM 本质上是对真实 DOM 的抽象和映射,用一个轻量级的 JavaScript 对象来描述页面结构。
当需要更新 UI 时,框架会先在内存中(虚拟 DOM)进行计算与对比,然后再将差异高效地应用到真实 DOM。这样的理念可以减少不必要的真实 DOM 操作,进而提升性能。
 
在 React 中,“ReactElement”是构造虚拟 DOM 的核心数据结构,一般通过 JSX 或 React.createElement(...) 来创建。一个典型的 ReactElement 对象包含以下信息:
• type:要渲染的节点类型(字符串代表普通 DOM 标签,如 'div';或一个自定义组件)。
• props:节点的属性或子元素等相关数据。
• key、ref 等内部标识符(帮助 React 快速判断节点变化,或为组件提供引用)。
 
这些“ReactElement”对象构成了 React 的虚拟 DOM 树,框架会根据它们与旧的虚拟 DOM 树进行对比后,找出需要更新的节点并执行真实 DOM 操作。
Virtual DOM 更新对比流程
 
React 在进行更新时,使用一种称为“调和(Reconciliation)”的过程:
1) 首先创建新旧虚拟 DOM 树的对比;
2) 判断节点类型、key 等以定位可复用节点;
3) 如果节点类型相同,则会进一步比较子元素;若不同,则放弃复用,销毁旧节点并新建节点;
4) 计算出对真实 DOM 用户界面所需的最少量操作,然后执行更新。
通过这种方式,React 避免了很多没必要的真实 DOM 重绘,性能相对较高
 

3.2.渲染流程

流程:
1. 编写 JSX 代码:

 
  • 开发者使用 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项目渲染过程的更多相关文章

  1. React源码解析之React.Children.map()(五)

    一,React.Children是什么? 是为了处理this.props.children(this.props.children表示所有组件的子节点)这个属性提供的工具,是顶层的api之一 二,Re ...

  2. React源码解析:ReactElement

    ReactElement算是React源码中比较简单的部分了,直接看源码: var ReactElement = function(type, key, ref, self, source, owne ...

  3. React源码解析-Virtual DOM解析

    前言:最近一直在研究React,看了陈屹先生所著的深入React技术栈,以及自己使用了这么长时间.对React应该说有比较深的理解了,正好前阵子也把两本关于前端设计模式的书看完了,总感觉有一种知识错综 ...

  4. React源码解析——ReactAPI

    一.API背景 api的具体转化关系 可以通过到https://babeljs.io/repl/网站去将我们创建的Jsx进行实时的转译 const React = { Children: { map, ...

  5. React源码解析:setState

    先来几个例子热热身: ......... constructor(props){ super(props); this.state = { index: 0 } } componentDidMount ...

  6. React源码解析——创建更新过程

    一.ReactDOM.render 创建ReactRoot,并且根据情况调用root.legacy_renderSubtreeIntoContainer或者root.render,前者是遗留的 API ...

  7. Android源码解析系列

    转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...

  8. React躬行记(16)——React源码分析

    React可大致分为三部分:Core.Reconciler和Renderer,在阅读源码之前,首先需要搭建测试环境,为了方便起见,本文直接采用了网友搭建好的环境,React版本是16.8.6,与最新版 ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  10. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

随机推荐

  1. BasicDataSourceFactory类简介

    BasicDataSourceFactory实现了javax.naming.spi.ObjectFactory接口.   因此,先从ObjectFactory学习.  一.ObjectFactory接 ...

  2. Flink Catalog

    概念 Catalog 提供了元数据信息,例如数据库.表.分区.视图以及数据库或其他外部系统中存储的函数和信息. 数据处理最关键的方面之一是管理元数据. 元数据可以是临时的,例如临时表.或者通过 Tab ...

  3. (Python基础教程之六)Python中的关键字

    Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...

  4. nginx之访问控制

    Nginx的源码提供了ngx_http_auth_basic_module这个模块,它可以来解决web访问认证的问题.这个模块是默认就编译进nginx的,可以直接拿来使用. ngx_http_auth ...

  5. echarts 的使用

    <template> // option 通过id行绑定     <div id="myRangChart" style="width: 100%;he ...

  6. 原生JS点名器,随机数

    因为工作内容的需要自己琢磨了一个随机数的点名器,很早就写出了一版,今天无意间又看到了之前写的代码,还是有很多bug的,今天做了完善在这里分享给大家 <script type="text ...

  7. webpack-dev-server配置https

    前情 最近在做一个浏览器通知的交互需求,但是查阅官方文挡,浏览器通知需要在https环境下才能工作,于是就研究怎么在开发环境下配置一个https服务器 STEP1 安装Chocolatey Choco ...

  8. SpringBoot 整合Swagger2 踩坑记录

    SpringBoot 整合Swagger2 踩坑记录 Failed to start bean 'documentationPluginsBootstrapper'; nested exception ...

  9. 【Amadeus原创】更改docker run启动参数

    经过一整天的摸索,答案: 没法直接修改.只能另外创建. 但是还好不用完全重头来,用docker commit命令可以基于当前修改的内容创建一个新的image. 执行docker 看看帮助先: Comm ...

  10. 【Amadeus原创】word图片隐藏在文字里了的终极解决办法

    终极解决方案: 点击该图片,然后,选择正文,即可.