react源码学习

fiber架构的设计理念

1、fiber概述
在现有React中,更新过程是同步的,这可能会导致性能问题。

当React决定要加载或者更新组件树时,会做很多事,比如调用各个组件的生命周期函数,计算和比对Virtual DOM,最后更新DOM树,这整个过程是同步进行的,也就是说只要一个加载或者更新过程开始,那React就会一鼓作气运行到底,中途绝不停歇。在此过程中浏览器渲染引擎处于挂起的状态,无法进行任何渲染,浏览器无法执行任何其他的任务,调用栈如下图
在这里插入图片描述
破解javascript中同步操作时间过长的方法其实很简单——分片。

把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。

React Fiber把更新过程碎片化,执行过程如下面的图所示,每执行完一段更新过程,就把控制权交还给React负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有紧急任务,那就去做紧急任务。

有了分片之后,更新过程的调用栈如下图所示,中间每一个波谷代表深入某个分片的执行过程,每个波峰就是一个分片执行结束交还控制权的时机。
在这里插入图片描述
维护每一个分片的数据结构,就是Fib

Fiber = {
  tag, // 标记不同的组件类型
  key, // ReactElement里面的key
  elementType, // ReactElement.type,也就是我们调用`createElement`的第一个参数
  type, // 一般是`function`或者`class`
  stateNode, // 在浏览器环境,就是DOM节点

  return, // 指向他在Fiber节点树中的`parent`,用来在处理完这个节点之后向上返回
  child, // 单链表树结构,指向自己的第一个子节点
  sibling, // 指向自己的兄弟结构,兄弟节点的return指向同一个父节点
  index,
  ref, // ref属性

  pendingProps, // 即将更新的props
  memoizedProps, // 更新props
  memoizedState, // 当前状态
  dependencies, // 一个列表,存放这个Fiber依赖的context

  flags, // Effect,用来记录当前fiber的tag,插入、删除、更新的状态
  subtreeFlags,
  deletions,
  updateQueue, // 该Fiber对应的组件产生的Update会存放在这个队列里面
  nextEffect, // 单链表用来快速查找下一下side effect
  firstEffect, // 自述中第一个side effect
  lastEffect, // 子树中最后一个side effect

  lanes, // 当前Fiber更新的优先级
  childLanes,
  // 在Fiber树更新的过程中,每个Fiber都会有一个跟其对应的Fiber
  // 我们称他为`current <==> workInProgress`
  // 在渲染完成之后他们会交换位置
  alternate,

  // 用来描述当前Fiber和他子树的`Bitfield`
  // 共存的模式表示这个子树是否默认是异步渲染的
  // Fiber被创建的时候他会继承父Fiber
  // 其他的标识也可以在创建的时候被设置
  // 但是在创建之后不应该再被修改,特别是他的子Fiber创建之前
  mode,
  // 其余为调试相关的,收集每个Fiber和子树渲染时间的
  //...
}

在react-hooks源码解析中我们主要涉及到memoizedState、updateQueue、flags字段。

setState具体实现

(1)首次渲染主要是初始化hook,将初始值存入hook内,将hook插入到fiber.memoizedState的末尾。

(2)setCount主要是将更新信息插入到hook.queue.penging的末尾。这里注意一下为什么没有直接更新hook.memoizedState呢?答案是react是批量更新的,需要将更新信息先存储下来,等到合适的时机统一计算更新。

(3)再次渲染主要是根据setCount存储的更新信息来计算最新的state。

为什么只能在函数最外层调用 Hook?为什么不要在循环、条件判断或者子函数中调用?

react 会生成一棵组件树(或Fiber 单链表)将hook插入到fiber.memoizedState的末尾。通过单链表的 next指针 按顺序串联所有的 hook。 所有memoizedState 数组是按 hook定义的顺序来放置数据的,如果 hook 顺序变化,memoizedState 并不会感知到。

双缓存Fiber树解决了当前帧画面计算量比较大,导致清除上一帧画面到绘制当前帧画面之间有较长间隙,就会出现白屏问题

React使用“双缓存”来完成Fiber树的构建与替换——对应着DOM树的创建与更新。
在React中最多会同时存在两棵Fiber树。当前屏幕上显示内容对应的Fiber树称为current Fiber树,正在内存中构建的Fiber树称为workInProgress Fiber树。当应用程序状态发生更改,并需要更新 UI 时,React Fiber 首先在 Work Buffer 中执行所有渲染操作,以避免将中间状态呈现在屏幕上。一旦 Work Buffer 中的所有渲染操作完成,React Fiber 将当前缓存与工作缓存进行切换,即将 Work Buffer 设置为当前缓存,以此来更新屏幕上的 UI。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值