React 17原理


两大工作循环
在执行reconcile的时候,并不会先去构造fiber,而是先去schedule调度中心申请 task,即把更新需求转换成一个task;然后调度中心执行task,构造fiber然后commitRoot
reconciler 运作流程
- 输入: 暴露
api
函数(如:scheduleUpdateOnFiber
), 供给其他包(如react
包)调用. - 注册调度任务: 与调度中心(
scheduler
包)交互, 注册调度任务task
, 等待任务回调. - 执行任务回调: 在内存中构造出
fiber树
, 同时与与渲染器(react-dom
)交互, 在内存中创建出与fiber
对应的DOM
节点.- 如果本次渲染被中断,会返回一个新的performConcurrentWorkOnRoot,等待下次执行
- 输出: 与渲染器(
react-dom
)交互, 渲染DOM
节点.
在最新稳定版v17.0.2
中, 可中断渲染
虽然实现, 但是并没有在稳定版暴露出 api. 只能安装 alpha 版本才能体验该特性.
Fiber树构造
探寻阶段 beginWork
- 根据
ReactElement
对象创建所有的fiber
节点, 最终构造出fiber树形结构
(设置return
和sibling
指针) - 设置
fiber.flags
(二进制形式变量, 用来标记fiber
节点 的增,删,改
状态, 等待completeWork阶段处理
) - 设置
fiber.stateNode
局部状态(如Class类型
节点:fiber.stateNode=new Class()
)
回溯阶段 completeWork
- 调用
completeWork
- 给
fiber
节点(tag=HostComponent, HostText)创建 DOM 实例, 设置fiber.stateNode
局部状态(如tag=HostComponent, HostText
节点: fiber.stateNode 指向这个 DOM 实例). - 为 DOM 节点设置属性, 绑定事件(这里先说明有这个步骤, 详细的事件处理流程, 在
合成事件原理
中详细说明). - 设置
fiber.flags
标记
- 给
- 把当前
fiber
对象的副作用队列(firstEffect
和lastEffect
)添加到父节点的副作用队列之后, 更新父节点的firstEffect
和lastEffect
指针. - 识别
beginWork
阶段设置的fiber.flags
, 判断当前fiber
是否有副作用(增,删,改), 如果有, 需要将当前fiber
加入到父节点的effects
队列, 等待commit
阶段处理.
Hooks
- 其中
hook.queue
与fiber.updateQueue
虽然都是update环形链表
, 尽管update对象
的数据结构与处理方式都高度相似, 但是这 2 个队列中的update对象
是完全独立的.hook.queue
只作用于hook对象
的状态维护, 切勿与fiber.updateQueue
混淆.
fiber.memoizedState 表示对应hook
hook.memoizedState : 保存内存中的局部状态并且还有更新的quene
hooks链表和ClassInstance一样,用于保存局部状态,里面的state变更都会引起重新渲染,但是各子组件需要保存自己的state状态