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 、属性操作、事件处理中解放出来。
相关推荐
大橙子额40 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
WooaiJava2 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
LYFlied2 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
Never_Satisfied2 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
WeiXiao_Hyy3 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
xjt_09014 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农4 小时前
Vue 2.3
前端·javascript·vue.js
辰风沐阳4 小时前
JavaScript 的宏任务和微任务
javascript
冰暮流星5 小时前
javascript之二重循环练习
开发语言·javascript·数据库