本文是对React Fiber知识点的学习记录,网上有很多大佬对React Fiber的详细讲解,想要深入了解React Fiber的可以查看文章后面的引用。
一、React Fiber是什么,解决了什么问题
React Fiber在React v16引入,相当于是对核心渲染机制的一次重构。在没有引入这种算法之前,React在所有更新都没有完成时会一直占用主线程,直接导致的现象是渲染期间页面的其他js动效会卡住直到主线程继续,使页面出现卡顿的现象。
看一个:Fiber Example Fiber Example
To install React, follow the instructions on GitHub.
If you can see this, React is not working right. If you checked out the source from GitHub make sure to run
npm run build
.
react fiber针对这种情况做了什么优化呢?主要是两点:1、将任务拆分成一小块一小块,2、获取到时间片才执行任务
下面主要来讲讲这两点二、React Fiber的任务拆分
学过React的都知道,React有虚拟dom树,vDom-tree,要把计算任务拆分,那就要有任务恢复和任务完成后提交等功能,普通的vDom并不具备记录这些信息的能力,因此React Fiber从虚拟节点衍生出了一套Fiber节点,来记录任务状态。每一个Fiber节点都会对应一个虚拟节点,这样计算任务就拆分成了一个个小块,类似于下图,会有一个对应关系
简单描述下它的流程:1.数据状态发生改变,即发生setState2.开始diff算法3.到达一个节点,生成对应的fiber节点,记录状态4.查看当前是否有执行时间5.有执行时间,计算完当前节点(节点的增删改),到下一个节点,继续这个步骤6.到某个节点没有执行时间,则保存fiber状态,每个fiber都记录了下一个任务指向7.重新获取到了执行时间,从当前记录的fiber节点开始往下继续8.执行到最后的节点,将结果进行一级一级提交,这样直到根节点,组件就知道它已经完成了数据计算9.最后一步,将最终确认的dom结果渲染到页面中三、如何获取到时间片的
这个就比较简单了,刚开始我还以为React使用了什么骚操作来弄得,看了大佬们的文章后才知道,原来是用了浏览器的api: 和,requestAnimationFrame会在每一帧结束后确定调用它的回调函数,用于处理高优先级任务,为了达到不影响页面效果requestIdleCallback用于处理低优先任务,它的执行时机不确定。主要说下requestIdleCallback,每次调用requestIdleCallback,会告诉你现在是否是空闲时间,空闲时间有多久,它的用法:
// 一窥它的行为requestIdleCallback(function(){ console.log('1'); let a = 1000000000; while(a > 0){ a--; }})requestIdleCallback(function(){console.log('2')})requestIdleCallback(function(){console.log('3')}, {timeout:10})// 使用方式const tasks = [...] // 任务队列function taskHandler(deadline) { // deadline.timeRemaining() 可以获取到当前帧剩余时间 while (deadline.timeRemaining() > 0 && tasks.length > 0) { // do something } // 没时间了,但还有任务,继续注册一个,等到下次有时间了会执行 if (tasks.length > 0){ requestIdleCallback(taskHandler); }}requestIdelCallback(taskHandler);
上面说到任务的优先级,在fiber任务执行完进行dom更新的时候,这块是没法做任务拆分的,如果遇到dom变化很大,更新耗时的情况也会造成卡顿,这个没法避免,如果此时有用户交互发生,造成卡顿会降低用户体验,Fiber针对这种情况也做了优化,将任务分成优先级,像用户输入,交互等行为属于高优先级,会优先处理,然后页面渲染,diff计算等属于次优先级。
几篇对React Fiber不错的介绍: