# React
# 18 有哪些更新
不再支持 IE
使用 renderRoot 替换 ReactDOM.render。默认支持并发渲染
自动批量更新
在
React 18
之前,我们只在React 事件处理函数
中进行批处理更新。默认情况下,在promise
、setTimeout
、原生事件处理函数
中、或任何其它事件内
的更新都不会进行批处理flushSync 立即更新,但是函数内部的多个 setState 仍然为批量更新
组件可以返回
undefined
,18 之前只能返回null
Strict Mode 严格模式,还是会打印 2 次,只是第二个是一个灰色的log
新api
useId
Concurrent Mode(并发模式)
useTransition 不阻塞 UI 的情况下更新。这个是延迟更新方法 case: 切换tab的时候,如果当前tab阻塞了渲染,那么立马切换到其他的tab就会卡顿。使用了 useTransition 就不会卡顿了。原理就是在 commit 之前,有更高优先级的任务插入,中断了提交渲染。
useDeferredValue 延迟更新。这个是延迟更新值
# React fiber
# 什么是 fiber,fiber解决了什么问题
React Fiber就是虚拟 DOM,它是一个链表结构,返回了return、child、sibling,分别代表父fiber,子fiber和兄弟fiber,随时可中断和恢复。解决在React16以前,React更新是通过 树的深度优先遍历 完成的,遍历是不能中断的,当树的层级深就会产生栈的层级过深,页面渲染速度变慢的问题
# 如何实现中断和恢复
时间片分割:React 将渲染任务分成多个小的时间片(time slices),每个时间片内处理一部分 Fiber 节点。(requestIdleCallback)
优先级调度:React 根据任务的优先级来调度任务。如果在处理一个时间片的过程中有更高优先级的任务(如用户输入),React 会暂停当前的任务。
状态保存:在暂停时,React 会保存当前的 Fiber 状态,包括已经处理的节点和未处理的节点。
恢复任务:一旦高优先级任务处理完毕,React 会恢复之前的工作,从上次暂停的地方继续处理剩余的 Fiber 节点。如果状态发生变化,React 可能需要重新计算部分或全部的 Fiber 树。
let nextUnitOfWork = null; // 当前需要处理的 Fiber 节点
let wipRoot = null; // 当前工作中的 Fiber 树的根节点
function workLoop(deadline) {
let shouldYield = false;
while (nextUnitOfWork && !shouldYield) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
shouldYield = deadline.timeRemaining() < 1; // 检查是否需要让出时间
}
if (!nextUnitOfWork && wipRoot) {
commitRoot(); // 提交阶段
}
requestIdleCallback(workLoop); // 请求下一个时间片
}
function performUnitOfWork(fiber) {
// 处理当前 Fiber 节点
// 返回下一个需要处理的 Fiber 节点
if (fiber.child) {
return fiber.child;
}
let nextFiber = fiber;
while (nextFiber) {
if (nextFiber.sibling) {
return nextFiber.sibling;
}
nextFiber = nextFiber.return;
}
return null;
}
function commitRoot() {
// 提交阶段,将更新应用到实际的 DOM
}
// 初始化工作循环
requestIdleCallback(workLoop);
# Fiber 树
“递”阶段
首先从rootFiber
开始向下深度优先遍历。为遍历到的每个Fiber节点
调用 beginWork 方法 (opens new window)。
该方法会根据传入的Fiber节点
创建子Fiber节点
,并将这两个Fiber节点
连接起来。
当遍历到叶子节点(即没有子组件的组件)时就会进入“归”阶段。
“归”阶段
在“归”阶段会调用 completeWork (opens new window) 处理Fiber节点
。
当某个Fiber节点
执行完completeWork
,如果其存在兄弟Fiber节点
(即fiber.sibling !== null
),会进入其兄弟Fiber
的“递”阶段。
如果不存在兄弟Fiber
,会进入父级Fiber
的“归”阶段。
“递”和“归”阶段会交错执行直到“归”到rootFiber
。至此,render阶段
的工作就结束了。
# 优先级是如何确定的
React Scheduler 定义了几个优先级级别,每个级别对应不同类型的任务:
- 同步优先级(Sync Priority):最高优先级,通常用于处理用户输入或其他需要立即响应的任务。
- 用户输入优先级(User Blocking Priority):次高优先级,用于处理用户交互,如点击和滚动。
- 普通优先级(Normal Priority):默认优先级,用于处理大多数常规更新,如定时器和数据加载。
- 低优先级(Low Priority):较低优先级,用于处理一些不紧急的更新,如后台数据加载。
- 无优先级(Idle Priority):最低优先级,用于处理一些可以在空闲时间完成的任务,如日志记录。
不同优先级
意味着不同时长的任务过期时间
React 中的优先级是使用 lane 模型调度的,31 个二进制
# React diff
# React Hooks
# setState 是同步的还是异步的
# React 渲染流程
# React 生命周期
# 参考资料
← 知识点