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 、属性操作、事件处理中解放出来。
相关推荐
POLITE326 分钟前
Leetcode 238.除了自身以外数组的乘积 JavaScript (Day 7)
前端·javascript·leetcode
闲蛋小超人笑嘻嘻1 小时前
非父子通信: provide和inject
前端·javascript·vue.js
周亚鑫1 小时前
vue3 js代码混淆
开发语言·javascript·ecmascript
止观止1 小时前
不止解构:深入掌握 ES6+ 对象与函数的高级语法糖
前端·javascript·es6
C_心欲无痕1 小时前
react - useTransition标记低优先级更新
前端·react.js·前端框架
捻tua馔...1 小时前
antd3的表单实现(HOC解决方案)
前端·javascript·react.js
AllinLin1 小时前
JS中的call apply bind全面解析
前端·javascript·vue.js
POLITE31 小时前
Leetcode 438. 找到字符串中所有字母异位词 JavaScript (Day 4)
javascript·算法·leetcode
创思通信1 小时前
STM32F103C8T6采 DS18B20,通过A7680C 4G模块不断发送短信到手机
javascript·stm32·智能手机
zhougl9961 小时前
vue中App.vue和index.html冲突问题
javascript·vue.js·html