React中渲染并提交的过程(转载React官网的文档)

164 阅读4分钟

前言

组件在屏幕上显示之前,必须先由 React 进行渲染。理解此过程的步骤将有助于你思考代码的执行方式并解释其行为。想象一下,你的组件就像厨房里的厨师,用各种食材烹制美味佳肴。在这个场景中,React 就像服务员,负责接收顾客的请求并送达订单。这个 UI 请求和服务流程分为三个步骤:

  1. 触发渲染(将客人的订单送至厨房)——扳机
  2. 渲染组件(在厨房准备订单)——使成为
  3. 提交DOM(将订单放在桌子上)——犯罪 image.png

步骤一:触发渲染

初始渲染

应用启动时,您需要触发初始渲染。框架和沙盒有时会隐藏此代码,但可以通过调用createRoot目标 DOM 节点,然后render使用组件调用其方法来完成:

import Image from './Image.js';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'))
root.render(<Image />);

export default function Image() { return ( 'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals );

状态更新时重新渲染

组件初始渲染完成后,您可以通过使用该set函数更新其状态来触发后续渲染。更新组件状态会自动将渲染加入队列。(您可以想象一下,餐厅的客人在下单后,根据口渴或饥饿的状态,点茶、甜点以及各种各样的东西。) image.png

步骤2:React 渲染你的组件

触发渲染后,React 会调用你的组件来确定在屏幕上显示什么。 “渲染”就是 React 调用你的组件。

  • 在初始渲染时,  React 将调用根组件。
  • 对于后续渲染,  React 将调用状态更新触发渲染的函数组件。

这个过程是递归的:如果更新后的组件返回了其他组件,React 会接下来渲染组件;如果该组件也返回了其他内容,React 会接下来渲染组件,以此类推。这个过程会一直持续,直到没有嵌套的组件,并且 React 确切地知道应该在屏幕上显示什么。

在下面的例子中,React 将调用Gallery()Image()多次: image.png image.png

image.png

  • 在初始渲染时,  React 会为、、和三个标签创建 DOM 节点<section>``<h1>``<img>
  • 在重新渲染期间,  React 会计算哪些属性(如果有)自上次渲染以来发生了变化。在下一步(提交阶段)之前,它不会处理这些信息。

(渲染必须始终是纯粹的计算

  • 相同的输入,相同的输出。 给定相同的输入,组件应该始终返回相同的 JSX。(当有人点了一份西红柿沙拉时,他们不应该收到一份洋葱沙拉!)
  • 它只管自己的事情。 它不应该更改渲染前已存在的任何对象或变量。(一个订单不应该影响其他订单。)

否则,随着代码库复杂度的增加,你可能会遇到令人困惑的 bug 和难以预测的行为。在“严格模式”下开发时,React 会调用每个组件的函数两次,这有助于发现由不纯函数引起的错误。)

步骤 3:React 将更改提交到 DOM

在渲染(调用)你的组件后,React 将修改 DOM。

  • 对于初始渲染,  React 将使用appendChild()DOM API 将其创建的所有 DOM 节点放到屏幕上。
  • 对于重新渲染,  React 将应用最少的必要操作(渲染时计算!)以使 DOM 与最新的渲染输出匹配。

仅当渲染之间存在差异时,React 才会更改 DOM 节点。 例如,下面这个组件每秒都会使用从其父级传递过来的不同 props 重新渲染。请注意,你可以向 中添加一些文本<input>,并更新其value,但当组件重新渲染时,文本不会消失。

结语:浏览器绘制

渲染完成并 React 更新 DOM 后,浏览器将重新绘制屏幕。虽然此过程被称为“浏览器渲染”,但为了避免混淆,我们将其称为“绘制”。

总而言之,- React 应用程序中的任何屏幕更新都分三个步骤进行:

  1. 扳机
  2. 使成为
  3. 犯罪

参考文献:react.dev/learn/rende…