当前位置: 首页 > 科技观察

面试官:说说你对ReactFiber架构的理解?它解决了什么问题?

时间:2023-03-21 00:14:26 科技观察

本文转载自微信公众号《JS日报》,作者慧慧。转载本文请联系JS每日一问公众号。1.问题JavaScript引擎和页面渲染引擎线程是互斥的。当其中一个线程执行时,另一个线程只能挂起等待。如果JavaScript线程长时间占用主线程,那么渲染层级的更新就无法进行。如果长时间不等待,界面会长时间不更新,导致页面响应不佳,用户可能会感到卡顿。这正是React15的StackReconciler面临的问题。React在渲染组件时,从开始到渲染完成的整个过程是一气呵成的,不能被打断。如果组件很大,js线程会继续执行,然后等到整个VDOM树计算完成后,才交给渲染线程。这将导致一些用户交互和动画。2.什么是反应纤维?这是Facebook在React上花费了两年多时间的一次重大改变和优化。它是对React核心算法的重新实现。Facebook在ReactConf2017会议上确认,ReactFiber在React16版本中发布在React中,主要做了以下操作:为每个任务添加优先级,高优先级的任务可以打断低优先级的任务。然后再试,注意重新执行低优先级的任务会增加异步任务,调用requestIdleCallbackapi,浏览器空闲时执行domdifftree变成链表。一个dom对应两个fiber(一个链表),对应两个Queue,就是找到中断的任务,重新执行。从架构的角度来看,Fiber是对React核心算法(即协调过程)的重写。从编码的角度来看,Fiber是React内部定义的一种数据类型。Structure,即Fiber树结构的节点单元,即React16新架构下的虚拟DOM。Fiber是一个JavaScript对象,它包含元素信息、更新操作队列和元素类型。它的数据结构如下:typeFiber={//用于标记fiber的WorkTag类型,主要表示当前fiber代表的组件类型,如FunctionComponent、ClassComponent等。第一个参数elementType:any,//Theresolvedfunction/class/associatedwiththisfiber.//表示当前表示的节点类型type:any,//表示当前FiberNode对应的元素组件实例stateNode:any,//指向他在Fiber节点树中的`parent`使用处理完这个节点向上返回return:Fiber|null,//指向它的第一个子节点child:Fiber|null,//指向自己的兄弟结构,兄弟节点的返回指向同一个父节点sibling:fiber|null,index:number,ref:null|(((handle:mixed)=>void)&{_stringRef:?string})|RefObject,//当前处理过程中的组件propsObjectpendingProps:any,//上次渲染完成后的propsmemoizedProps:any,//生成的UpdateFiber对应的组件会存储在这个队列中updateQueue:UpdateQueue<any>|null,//statememoizedStateatthetimeoflastrendering:any,//一个列表,用来存放这个Fiber所依赖的contextfirstContextDependency:ContextDependency|null,mode:TypeOfMode,//Effect//used记录SideEffecteffectTag:SideEffectTag,//单链表用于快速查找下一个sideeffectnextEffect:Fiber|null,//子树中第一个sideeffectfirstEffect:Fiber|null,//子树中最后一个sideeffectlastEffect:fiber|null,//表示任务应该在未来的什么时间点完成,然后版本会更名为lanesexpirationTime:ExpirationTime,//快速判断子树是否有变化不等待alternate:Fiber|null,}3.如何解决Fiber?将渲染更新过程拆分成多个子任务,每次只做一小部分。完成后,检查是否还有时间。如果是,继续下一个任务;如果不是,则挂起当前任务,把时间控制权交给主线程,等主线程不忙的时候继续执行,就可以打断再恢复。恢复后,也可以重用之前的中间状态,不同的任务被赋予不同的优先级。level,其中每个任务更新单元是ReactElement对应的Fiber节点。上面的方法就是requestIdleCallback方法window.requestIdleCallback()方法将浏览器空闲期间调用的函数排队。这使开发人员能够在主事件循环中运行。在不影响延迟的情况下对动画和输入响应等关键事件执行后台和低优先级工作。首先,React中的任务被分成多个步骤并分批完成。在完成部分任务后,将控制权交还给浏览器,让浏览器有时间重新渲染页面。等待浏览器繁忙后的剩余时间,再继续React未完成的任务,是一种协同调度。实现过程基于Fiber节点。作为一个静态数据结构,每个Fiber节点对应一个React元素,其中存储了组件的类型(功能组件/类组件/原生组件等),对应的DOM节点等信息。作为一个动态的工作单元,每个Fiber节点保存了本次更新中组件改变的状态以及要执行的工作。每个Fiber节点都有对应的React元素,多个Fiber节点根据以下三个属性构建树://指向父Fiber节点this.return=null//指向子Fiber节点this.child=null//指向右边第一个兄弟Fiber节点this.sibling=null通过这些属性可以找到下一个执行目标。/vue3js.cn/面试