【超硬核】React源码设计思想(一)Fiber

发布于:2022-12-15 ⋅ 阅读:(224) ⋅ 点赞:(0)

在这里插入图片描述

一、设计背景

在浏览器中,JS 运算、页面布局和页面绘制都是运行在浏览器的主线程当中,他们之间是互斥的关系。通常这时,对于用户在输入框输入内容这个行为来说,就体现为按下了键盘按键但是页面上不实时显示输入。
用户的交互得不到及时的响应,这对网页的用户体验来说是非常不利的

二、优化思路

将运算切割为多个步骤,分批完成。说在完成一部分任务之后,将控制权交回给浏览器,让浏览器有时间进行页面的渲染。等浏览器忙完之后,再继续之前未完成的任务。
这就是React 16中的Fiber设计思想。

简而言之:就是将计算的粒度分割比较小,方便不同功能的组合

三、Fiber到底是什么?

fiber其实仅仅就是一个JS对象,它与react instance 一一对应,是调和阶段stack所能拆解的最小工作单元。
一个fiber链接着下一个fiber,整个结构就是一个单向链表树。也就是Fiber tree。

Fiber的主要目的是尽可能的发挥scheduling的优势,其主要表征特点有以下几方面:

  1. 为不同的类型的工作指定优先级
  2. 能停下来然后返回继续
  3. 重用以前完成了的工作
  4. 释放那些不再需要的工作

四、Fiber的实现

Fiber实现了自己的组件调用栈,它以链表的形式遍历组件树,可以灵活的暂停、继续和丢弃执行的任务。实现方式是使用了浏览器的requestIdleCallback这一 API。
window.requestIdleCallback()会在浏览器空闲时期依次调用函数,这就可以让开发者在主事件循环中执行后台或低优先级的任务,而且不会对像动画和用户交互这些延迟触发但关键的事件产生影响。函数一般会按先进先调用的顺序执行,除非函数在浏览器调用它之前就到了它的超时时间。

五、具体设计

分层设计

Virtual DOM 层
描述页面长什么样
Reconciler 层
负责调用组件生命周期方法,进行 Diff 运算等
Renderer 层
根据不同的平台,渲染出相应的页面,比较常见的是 ReactDOM 和 ReactNative

执行阶段

阶段一

生成 Fiber 树,得出需要更新的节点信息。这一步是一个渐进的过程,可以被打断。

可被打断的特性,让优先级更高的任务先执行,从框架层面大大降低了页面掉帧的概率。

阶段二

将需要更新的节点一次过批量更新,这个过程不能被打断。

六、 数据结构

链表

fiber 采用链表的形式。

    stateNode,    // 节点实例  本身
    child,        // 子节点next
    sibling,      // 兄弟节点
    return,       // 父节点pre

在这里插入图片描述

Fiber树

Fiber Reconciler 在阶段一进行 Diff 计算的时候,会生成一棵 Fiber 树。这棵树是在 Virtual DOM 树的基础上增加额外的信息来生成的,它本质来说是一个链表。
![在这里插入图片描述](https://img-blog.csdnimg.cn/5524f842c2384173be7fdb2141fcdba2.png
Fiber 树在首次渲染的时候会一次过生成。在后续需要 Diff 的时候,会根据已有树和最新 Virtual DOM 的信息,生成一棵新的树。这颗新树每生成一个新的节点,都会将控制权交回给主线程,去检查有没有优先级更高的任务需要执行
在这里插入图片描述

七、Scheduler(调度器)

synchronous,与之前的Stack Reconciler操作一样,同步执行
task,在next tick之前执行
animation,下一帧之前执行
high,在不久的将来立即执行
low,稍微延迟执行也没关系
offscreen,下一次render时或scroll时才执行

总结:React 16 Fiber 设计思路 :可中断+优先级执行
未完待续,下一篇:Fiber 协调器Reconciler(render阶段)


网站公告

今日签到

点亮在社区的每一天
去签到