渲染和提交
🔄 React渲染的三个步骤
React将组件显示到屏幕上的过程可以比喻为餐厅服务流程:
- 触发渲染 📣 - 类似服务员接收订单
- 渲染组件 👨🍳 - 类似厨师准备食物
- 提交到DOM 🍽️ - 类似服务员将食物送到桌上
📣 步骤1:触发渲染
有两种情况会触发渲染:
🔰 初次渲染
- 应用启动时通过
createRoot
创建根节点 - 调用
root.render(<App />)
将组件放入DOM容器
jsx
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
🔄 状态更新重新渲染
- 组件通过
setState
函数更新状态 - 状态更新会自动将渲染请求加入队列
👨🍳 步骤2:React渲染组件
触发渲染后,React会调用组件确定要显示的内容:
- 初次渲染:React调用根组件
- 重新渲染:React调用触发更新的函数组件
渲染过程是递归的:
- 如果组件返回其他组件,React会继续渲染那些组件
- 这个过程持续直到React知道所有要显示的内容
⚠️ 渲染的重要特性
渲染必须是纯计算:
- 相同输入,相同输出:给定相同的props和state,组件应始终返回相同的JSX
- 不修改已有对象:不应更改渲染前存在的对象或变量
- 无副作用:不应在渲染期间发送请求、设置超时、修改DOM等
💡 在严格模式下,React会调用每个组件的函数两次,帮助发现不纯函数导致的问题
🍽️ 步骤3:React提交更改到DOM
完成组件渲染后,React会修改DOM:
- 初次渲染:使用
appendChild()
DOM API将所有创建的DOM节点放到屏幕上 - 重新渲染:仅应用必要的最小操作,使DOM与最新渲染输出匹配
React只会更新实际发生变化的DOM部分!如果渲染结果与上次相同,React不会修改DOM。
🎨 浏览器绘制
DOM更新后,浏览器会重新绘制屏幕。这个过程称为"浏览器绘制"(browser painting)。
💡 性能优化提示
- React默认会渲染更新组件及其所有嵌套组件
- 如果性能出现问题,可以使用以下技术优化:
memo()
:跳过不必要的重渲染useMemo()
:缓存计算结果useCallback()
:缓存函数定义
⚠️ 不要过早优化!先理解渲染流程,在真正需要时再进行优化
📝 总结
- 🔄 React渲染过程包括三个步骤:触发、渲染和提交
- 🔰 初次渲染通过
createRoot
和root.render()
触发 - 🔄 状态更新会触发重新渲染
- ⚛️ React递归渲染组件直到没有更多嵌套组件
- 🧪 使用严格模式可以发现渲染中的不纯操作
- 🎯 React只更新必要的DOM部分,这是其高效性能的关键