0%

已完成 0/29 关

教学模式

你可以随时调整。

此设置调整教师的教学方式,无需重新生成课程。

第 15 关 含代码 约 8 分钟

渲染和提交:触发、渲染计算与 DOM 提交三步曲

渲染和提交:触发、渲染计算与 DOM 提交三步曲

许多初学者常常把“React 渲染”与“把画面画在浏览器上”混为一谈。事实上,在你的组件向用户展示最新内容之前,需要经历一套精密的流水线处理。

理解这套流程的最佳方式,是把它想象成 在一家高级餐厅就餐的三个步骤:

  1. 触发点单(Triggering):把顾客的菜单送到后厨;
  2. 在后厨烹饪制作(Rendering):厨师根据菜单调配食材并制作菜品;
  3. 端菜上桌提交(Committing):服务员把做好的精美菜肴稳稳摆在顾客面前。

让我们来看看 React 内部的这三步曲。


步骤一:触发一次渲染(Triggering a render)

有且仅有两种原因会引发 React 启动渲染:

1. 组件的初次渲染(Initial Render)

当你的网页刚刚打开,React 必须把所有的组件从无到有挂载在屏幕上。这相当于顾客刚刚走进餐厅,坐下并完成了第一份点单。在底层,这通常由 createRoot(...).render(<App />) 发起。

2. 状态改变后的重新渲染(Re-render on state update)

当组件已经在屏幕上展示后,用户进行了某些操作(如点击按钮、输入表单),你调用了 set 函数(例如 setCount(count + 1))。 调用 set 函数并不是立刻就地修改 DOM,而是像顾客按下了呼叫铃:“服务员,我要加菜!”,向 React 排队登记了一次重新渲染的请求。


步骤二:React 渲染你的组件(Rendering your components)

“渲染(Rendering)”在 React 的语境里有一个非常精准的定义: 渲染就是 React 正在调用你的组件函数!

  • 在初次渲染时:React 会调用根组件函数,并沿着层级向下依次调用所有子组件;
  • 在后续重新渲染时:React 会调用那个触发了 state 更新的组件函数。如果该组件返回了其他子组件,React 还会继续递归调用这些子组件,以计算出在新的状态下,界面到底应该长成什么样。

核心原则:渲染过程必须是纯粹的计算! 正如我们在纯函数那一关所学的:厨师在后厨做菜时,绝对不能跑到大堂偷吃客人的面包。组件在渲染计算 JSX 的过程中,不能修改任何外部变量,不能直接操作 DOM 节点,它只负责计算并返回最新的 JSX 描述树!


步骤三:React 把更改提交到 DOM(Committing to the DOM)

在渲染完成(即组件函数全部执行完毕,得到了最新的 JSX 虚拟描述)后,React 进入“提交(Commit)”阶段:

  • 初次渲染:React 使用浏览器原生 DOM API(如 appendChild())把所有生成的真实 DOM 节点直接插入到 HTML 页面中;
  • 重新渲染:这是 React 最具魔法的地方! React 会把刚刚计算出的最新 JSX 树,与上一次渲染的旧 JSX 树进行精密的逐项比对(Diffing)。 React 只会对发生了实际变化的 DOM 节点进行最小化修改!

极具说服力的现场实验:

观察下面这个每秒钟更新一次时钟的组件:

export default function Clock({ time }) {
  return (
    <>
      <h1>当前时间: {time}</h1>
      <input placeholder="在这里输入文字测试..." />
    </>
  );
}

每过一秒钟,time 状态更新,React 就会重新调用 Clock 函数。 但是,如果你在下方的 <input> 输入框里正在敲字,你会惊奇地发现: 即使每秒钟都在重新渲染,你的输入法、打到一半的拼音、光标位置丝毫没有受到任何影响!

为什么?因为 React 比对后发现,<input> 标签的属性和上一次相比没有任何变化!于是在提交阶段,React 完全不去触碰真实的 input DOM 节点,只精准更新了 <h1> 里的时间文本!


尾声:浏览器的屏幕绘制(Browser Paint)

当 React 完成 DOM 提交后,浏览器的底层排版引擎(渲染引擎)就会介入,重新计算界面的几何尺寸、样式重排,并把像素真正绘制在显示器屏幕上。这一过程被称为浏览器的 重绘(Paint / Repaint)。


总结

记住这三步流水线:

  1. 触发(Trigger):初次挂载或调用 set 函数排队登记点单;
  2. 渲染(Render):React 调用你的组件函数,在后厨计算出最新的 JSX 结构树;
  3. 提交(Commit):React 找出新旧差异,仅对发生变动的真实 DOM 执行最小化手术级更新;
  4. 随后,浏览器将最终结果绘制到屏幕上。
下一站:State 如同一张快照:理解单次渲染中的常量状态 →
© 2026 React 官方教程