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 、属性操作、事件处理中解放出来。
相关推荐
工业甲酰苯胺6 小时前
TypeScript枚举类型应用:前后端状态码映射的最简方案
javascript·typescript·状态模式
止观止7 小时前
React虚拟DOM的进化之路
前端·react.js·前端框架·reactjs·react
谢尔登7 小时前
【React Natve】NetworkError 和 TouchableOpacity 组件
前端·react.js·前端框架
G等你下课9 小时前
React 路由懒加载入门:提升首屏性能的第一步
前端·react.js·前端框架
谢尔登10 小时前
【React Native】ScrollView 和 FlatList 组件
javascript·react native·react.js
然我10 小时前
面试官:如何判断元素是否出现过?我:三种哈希方法任你选
前端·javascript·算法
kk_stoper11 小时前
如何通过API查询实时能源期货价格
java·开发语言·javascript·数据结构·python·能源
晨枫阳11 小时前
前端VUE项目-day1
前端·javascript·vue.js
颜酱11 小时前
抽离ant-design后台的公共查询设置
前端·javascript·ant design
FogLetter11 小时前
深入浅出React-Router-Dom:从前端路由到SPA架构的华丽转身
前端·react.js