Fiber执行阶段

16.0之前的协调

  • React会递归对比VirtualDOM树,找出需要变动的节点,然后同步更新它们。这个过程React称为Reconcilation(协调)阶段。
  • 在Reconcilation期间,React会一直占用浏览器资源,这样会导致用户触发的事件得不到响应,二则会导致掉帧,用户会感到顿卡。

Fiber是什么

  • 可以通过某种调度策略来分配cpu资源,从而提高用户的响应速度。
  • 通过Fiber架构,让自己的Reconcilation过程变成可以中断,在适当的时候让出CPU的执行权,除了可以让浏览器及时地响应用户的交互。

Fiber是一个执行单元

  • Fiber是一个执行单元,每次执行完一个执行单元,React就会检查现在还剩多少时间,如果没有时间就将控制权让出去。

react与浏览器的任务调度.png

Fiber是一种数据结构

目前React采用的做法是使用链表,每个VirtualDOM节点内部表示为一个Fiber,

type Fiber = {
  type: any,
  return: Fiber,
  child: Fiber,
  sibling: Fiber,
}
type Fiber = {
  type: any,
  return: Fiber,
  child: Fiber,
  sibling: Fiber,
}

Fiber的执行阶段

  • 每次渲染有两个阶段: Reconciliation(协调\render阶段)和Commit提交阶段。
  • 协调阶段: 可以认为是Dif分阶段,这个阶段可以被中断,这个阶段会找出所有节点变更,例如新增,删除,属性变更等,这些变成React称之为副作用(Effect)。
  • 提交阶段:将上一个阶段计算出来的需要处理的副作用一次性执行了,这个阶段必须是同步执行,不能被打断。

render阶段

  • render阶段会构建fiber数
let A1 = { type: 'div', key: 'A1' };
let B1 = { type: 'div', key: 'B1', return: A1 };
let B2 = { type: 'div', key: 'B2', return: A1 };
let C1 = { type: 'div', key: 'C1', return: B1 };
let C2 = { type: 'div', key: 'C2', return: B1 };
A1.child = B1;
B1.sibling = B2;
B1.child = C1;
C1.sibling = C2;
module.exports = A1;
let A1 = { type: 'div', key: 'A1' };
let B1 = { type: 'div', key: 'B1', return: A1 };
let B2 = { type: 'div', key: 'B2', return: A1 };
let C1 = { type: 'div', key: 'C1', return: B1 };
let C2 = { type: 'div', key: 'C2', return: B1 };
A1.child = B1;
B1.sibling = B2;
B1.child = C1;
C1.sibling = C2;
module.exports = A1;
  • 从顶点开始遍历
  • 如果有第一个儿子,先遍历第一个儿子
  • 如果没有第一个儿子,标志着此节点遍历完成
  • 如果有弟弟遍历弟弟
  • 如果没有下一个弟弟,返回父节点表示完成父节点遍历,如果有叔叔遍历叔叔
  • 没有父节点则遍历结束。

遍历规则.png