React设计原理学习

351 阅读3分钟

框架原理

如何组织UI与逻辑

组件内部工作流程

image.png

架构

image.png

Schedule阶段

lane模型在React中的应用

image.png

状态更新流程

事件系统

  1. 合成事件
  2. 事件传播机制

对合成事件的理解

  1. react组件中编写的事件是绑定在dom上么,如果不是绑定在哪里? 绑定在fiber节点的属性中;在react首次挂载时,给根元素绑定了用于接受委托的函数,当事件发生时,所有事件都委托给根元素处理;处理的过程中,react会找到事件发生的dom对应的fiber,并通过收集其到根节点的路径上的节点相应的事件回调函数,最终来模拟捕获、冒泡的实现
  2. 为什么不能用 return false 来阻止事件的默认行为?
  3. react怎么通过dom元素,找到与之对应的 fiber对象的?dom对象上设置了能找到对应fiber的属性

ReactDOM.createRoot流程

image.png

useState流程

使用useState触发更新时,会调用源码的dispatchSetState方法

其中,会使用isRenderPhaseUpdate(fiber)判断是否是render阶段触发的更新

个人理解:如果是在render阶段,是否开启新的调度取决于调度器的分配;在其他阶段,则可以直接开启新的调度

性能优化

eagerState策略

如果某个状态更新前后没有变化,则可以跳过后续更新流程

时机:在更新发生时,schedule流程之前进行;

判断:当前fiberNode不存在‘待执行的更新’;此时触发的这个更新产生的更新是当前fiberNode中第一个带执行的更新,计算state不受其他update影响

命中条件:更新前后状态没有变化

结果:这个更新跳过后续的流程,不会更新fiebrNode.lanes

bailout策略

父组件命中bailout,则复用子fiber, 也就是说父组件bailout决定是否复用子fiber

React fiber中自变量包括state、props、context,第一次bailout对这三种变量有没有变化进行判断,命中则表示当前fiber没有变化

疑问

  • 第二次判断bailout中,如果有更新但state无变化,则表示命中bailout,那是否意味这与props和context是否变化无关?

image.png

对日常开发的启示

追求写出满足bailout策略的组件

  • 默认情况下(没有性能优化api以及不是有更新但无状态变化的情况),fiberNode要命中bailout策略需要满足oldProps===newProps,这意味着在默认情况下,如果父fiber没有命中策略,子fiberNode就不会命中策略,后代的fiberNode都不会命中策略
  • 值得注意的是,对于第一次没有命中bailout的情况,在第二次判断是否命中bailout前,会先执行组件的渲染。也就是说,对于在执行render时有耗时任务的组件,只要没有命中bailout,就不可避免的要进行render以及其中的耗时任务的执行。因此,在开发中,应该尽量对有耗时任务的组件进行分离,并且最好将其放在常常会命中bailout的父组件中