React的渲染流程

一、Babel的转化

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script crossorigin src="../lib/react.js"></script>
    <script crossorigin src="../lib/react-dom.js"></script>
    <script src="../lib/babel.js"></script>
    <script type="text/babel">
        class App extends React.Component {
            constructor(){
                super()
                this.state = {
                    message:"hello world"
                }
            }
            render(){
                return(
                    <div>
                        <div className="header">header</div>
                        <div className="content">
                            <ul>
                                <li>列表数据1</li>
                                <li>列表数据2</li>
                                <li>列表数据3</li>
                                <li>列表数据4</li>
                                <li>列表数据5</li>
                            </ul>
                        </div>
                        <div className="footer">footer</div>
                    </div>
                )
            }
        }
        const root = ReactDOM.createRoot(document.querySelector("#root"))
        root.render(<App/>)
    </script>
</body>
</html>

render 函数中的代码经过 Babel ,将代码进行转化,每遇到一个标签将元素转化成 React.createElement("div",{class,id},[]) ,子元素通过嵌套关系形成一个树结构,这个树结构就是指虚拟 DOM ,根据虚拟 DOM 最终渲染出一个真实 DOM 。

实际上, jsx 仅仅只是 React.createElement(component,props,..children) 函数的语法糖。所有的 jsx 最终都会被转换成 React.createElement 的函数调用。

createElement 需要传递三个参数:

参数一:type

  • 当前 ReactElement 的类型;
  • 如果是标签元素,那么就使用字符串表示 "div" ;
  • 如果是组件元素,那么就直接使用组件的名称。

参数二:config

  • 所有 jsx 中的属性都在 config 中以对象的属性和值的形式存储;
  • 比如传入 className 作为元素的 class 。

参数三:children

  • 存放在标签中的内容,以 children 数组的方式进行存储;
  • 当然,如果是多个元素, React 内部有对它们进行处理。

使用 babel 工具将代码转化为原生 js 后:

‌**_jsx**‌:这是 Babel 在转换 JSX 时生成的一个函数,用于将 JSX 语法转换为普通的 JavaScript 代码。例如,<div>Hello</div>会被转换为React.createElement('div', null, 'Hello')。这个函数通常用于优化性能,因为它减少了在每次渲染时重新创建元素的需要‌。

_jsxs‌:这是 Babel 在处理多个子元素的 JSX 时使用的函数。与 _jsx 类似, _jsxs 用于将多个子元素的 JSX 转换为 JavaScript 代码。例如,<div><p>Hello</p><p>World</p></div>会被转换为React.createElement('div', null, React.createElement('p', null, 'Hello'), React.createElement('p', null, 'World'))。这个函数同样是为了优化性能,减少不必要的元素创建‌。

二、虚拟DOM的创建过程

我们通过 React.createElement 最终创建出来一个 ReactElement 对象,这是一个 js 对象,是一个虚拟节点,是元素对象形式在 js 中的一种表示。

ReactElement 对象得作用:

  • 原因是 React 利用 ReactElement 对象组成了一个JavaScript 的对象树
  • JavaScript 的对象树就是虚拟DOM对象 (Virtual DOM)

虚拟DOM的作用:

  • 更新数据时候不需要更新所有 dom ,使用 diff 算法对新旧 dom 进行对比,只更新数据发生改变的 dom ;
  • 跨平台ReactNative:虚拟 DOM 通过 React 可以渲染成 web 的元素,还可以渲染成iOSAndroid控件,用 React 语法写原生代码。
  • 虚拟 DOM 帮助我们从命令式编程转到了声明式编程的模式

三、虚拟DOM转化为真实DOM

React 将虚拟 DOM 节点,使用 ReactDOM.render() 转化为 document.createElement("div") 这种真实 DOM 。

React 官方的说法:Virtual DOM是一种编程理念。

  • 在这个理念中, UI 以一种理想化或者说虚拟化的方式保存在内存中,并且它是一个相对简单的 JavaScript 对象;
  • 我们可以通过 ReactDOM.render 让虚拟 DOM 和真实 DOM 同步起来,这个过程中叫做协调(Reconciliation)。

这种编程的方式赋予了 React 声明式的 API :

  • 只需要告诉 React 希望让 UI 是什么状态;
  • React 来确保 DOM 和这些状态是匹配的;
  • 不需要直接进行 DOM 操作,就可以从手动更改 DOM 、属性操作、事件处理中解放出来。
相关推荐
OEC小胖胖7 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水7 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
老虎06277 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
三水气象台7 小时前
用户中心Vue3网页开发(1.0版)
javascript·css·vue.js·typescript·前端框架·html·anti-design-vue
烛阴8 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript
CN-Dust8 小时前
[FMZ][JS]第一个回测程序--让时间轴跑起来
javascript
全宝10 小时前
🎨前端实现文字渐变的三种方式
前端·javascript·css
yanlele10 小时前
前端面试第 75 期 - 2025.07.06 更新前端面试问题总结(12道题)
前端·javascript·面试
妮妮喔妮10 小时前
【无标题】
开发语言·前端·javascript
fie888910 小时前
浅谈几种js设计模式
开发语言·javascript·设计模式