React Fiber做出了哪些变化?
fiber是对react核心算法的重写。
为什么引入fiber?
React的更新特点是,当前组件触发更新的时候,以当前组件为根组件的所有子组件都要重新渲染,而React的组件化和标签化,都是嵌套关系,所以在更新的时候,diff过程会形成一种递归的调用,类似函数调用栈。但是栈的问题就在于不能随意中断,直至返回结果为止。这个就出现问题了,当我们组件数量很庞大的时候,diff算法耗时就会比较长,而浏览器的JS线程和GUI渲染线程是互斥的,JS线程占用时间过长,会导致页面的卡顿,尤其动画效果。比如用户输入的卡顿,敲了半天键盘,页面上没有任何响应,过了一会儿,可能屏幕上瞬间出现了很多文字。
基于上述问题,Fiber要做的是,当浏览器有更高优先级的任务时,React要让出主线程,也就意味着React的更新过程要可以被暂停。
1、数据结构的变化

从虚拟DOM tree变成了fiber tree,节点从vnode变成了fiber node,
由原来的栈结构变成了链表结构,有三个节点,父节点return、子节点child、兄弟节点sibling
在构造 Fiber 树的过程中,Fiber Reconciler 会将需要更新的节点信息保存在Effect List当中,在阶段二执行的时候,会批量更新相应的节点。
为了解决 diff 时间过长导致的卡顿问题,React Fiber 用类似 requestIdleCallback 的机制来做异步 diff。但是之前的数据结构不支持这样的实现异步 diff,于是 React 实现了一个类似链表的数据结构,将原来的 递归diff 变成了现在的 遍历diff,这样就能方便的做中断和恢复了。
2、任务优先级,任务的中断
React的Fiber利用浏览器的空闲之间来执行一些任务,这样就会防止出现掉帧卡顿的现象
提供2个api方法:requstIdleCallback — 可以在空闲期调用空闲期回调,执行任务。
requestAnimationFrame — 处理高优先级的任务
1)、任务拆分
diff更新过程
更新之后的commit去操作真实DOM
动画
用户输入
…
React给每个任务分配可执行时间,通过调用requstIdleCallback来依次执行Task Quene中的任务
Fiber要利用主线程的这个空闲时间,首先要对任务进行拆分,任务拆分后给每个任务分配一个可执行时间,然后加入到任务队列中,再通过调用
2)、任务优先级
通过限制任务的执行时间来控制优先级
执行时间越短,代表优先级越高
例如:更新真实DOM的操作,可以设置到期时间为0,表示可立即执行,优先级比较高
3、生命周期的变化
Fiber主要分为两个阶段: 1、Render阶段——diff过程 2、Commit 阶段——更新真实DOM并调用生命周期方法
也就是render阶段的可能会被执行多次,其中的生命周期也会执行多次。阶段一可被打断的特性,让优先级更高的任务先执行,从框架层面大大降低了页面掉帧的概率。
新增了getDerivedStateFromProps、getSnapshotBeforeUpdate两个静态方法来代替弃用的三个钩子函数(componentWillMountcomponentWillReceivePorps,componentWillUpdate)


网友评论