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 、属性操作、事件处理中解放出来。
相关推荐
小殷要努力刷题!3 小时前
JavaWeb项目——如何处理管理员登录和退出——笔记
java·javascript·笔记·学习·servlet·javaweb·寒假
忘不了情3 小时前
react中,使用antd的Upload组件上传zip压缩包文件
前端·javascript·react.js
Bingo_BIG4 小时前
uni-app main.js中全局变量的使用
javascript·vue.js·uni-app
Bingo_BIG5 小时前
uni-app vue3 常用页面 组合式api方式
前端·javascript·uni-app
十三月❀6 小时前
当设置dialog中有el-table时,并设置el-table区域的滚动,看到el-table中多了一条横线
javascript·vue.js·elementui
牧云流6 小时前
Vue3数据响应式原理
javascript·vue.js·ecmascript
不爱学英文的码字机器6 小时前
[JavaScript] 深入理解流程控制结构
开发语言·前端·javascript
不爱学英文的码字机器6 小时前
[JavaScript] 运算符详解
开发语言·javascript·ecmascript
Lysun0017 小时前
redux 结合 @reduxjs/toolkit 的使用
开发语言·前端·javascript·react·redux