看完React源码,相信大家对Fiber会有不同的看法,而我对Fiber最大的看法就是这个东西是一个链表。如果把整个Fiber树作为一个整体来看,源码确实很难看懂,但是如果拆开来看,把每个节点都当成一个独立的单元,思路就很清晰了。接下来我简单说一下,在我看来,React为什么要使用链表数据结构来构建Fiber架构?什么是纤维?可能了解React的人会说,Fiber是一棵虚拟的DOM树;确实如此,但是版本16之前的React也存在。虚拟dom树,为什么要用Fiber代替?众所周知(可能有些小白不知道),在16.8之前,React并没有引入Fiber的概念,Reconciler(协调器)会在mount阶段和update阶段递归mountComponent和updateComponent。这个时候数据是存放在调用栈中的,因为是递归执行的。所以一旦开始,就不能停止,直到递归执行结束;如果此时页面中的节点很多,等到递归结束可能会花费很多时间,用户在这段时间会有卡顿的感觉,这对用户来说是绝对必要的。不能称之为好的体验;所以在16版本之后,React有了异步可中断更新和双缓冲的概念,也就是大家熟知的同步并发模式Concurrentmode,那么这和Fiber有什么关系呢?首先我们看一段关于Fiber节点的React源码this.elementType=null;//this.type=null;//类型this.stateNode=null;//Fiber//关联属性this.return=null;this.child=null;this.sibling=nullthis.index=0;this.ref=null;//工作属性this.pendingProps=pendingProps;this.memoizedProps=null;this.updateQueue=null;吨his.memoizedState=null;this.dependencies=null;this.mode=模式;//效果this.flags=NoFlags;this.subtreeFlags=NoFlags;这个。删除=空;this.lanes=NoLanes;this.childLanes=NoLanes;this.alternate=null;{//注意:执行以下操作是为了避免v8性能悬崖。////将下面的字段初始化为smis并稍后使用双精度值更新它们将导致纤维最终具有单独的形状。//此行为/错误与Object.preventExtension()有关。//幸运的是,这只会影响DEV构建。//不幸的是,它使React对于某些应用程序来说非常慢。//要解决此问题,请使用双精度初始化下面的字段。////在这里了解更多信息://https://github.com/facebook/react/issues/14365//https://bugs.chromium.org/p/v8/issues/detail?id=8538this.actualDuration=Number.NaN;this.actualStartTime=Number.NaN;这个.selfBaseDuration=Number.NaN;this.treeBaseDuration=Number.NaN;//初始化后用smis替换初始的double就可以了。//这不会触发上面提到的性能悬崖,//它简化了其他分析器代码(包括DevTools)。this.actualDuration=0;this.actualStartTime=-1;this.selfBaseDuration=0;this.treeBaseDuration=0;}{//这不是直接使用的,但对于内部调试很方便:this._debugSource=null;this._debugOwner=null;this._debugNeedsRemount=false;this._debugHookTypes=null;if(!hasBadMapPolyfill&&typeofObject.preventExtensions==='function'){Object.preventExtensions(this);}}}可以看到一个FiberNode中有很多属性,我们大致分为三类:静态属性:保存当前Fiber节点的标签、类型等;关联属性:用于连接其他Fiber节点,组成一棵Fiber树;工作属性:保存当前Fiber节点的一个动态工作单元;多个Fiber节点通过关联属性的连接,组成一棵Fiber树;因为每个Fiber节点都是相互独立的,所以Fiber节点是通过指针链接起来的,return指向的是父节点,child指向的是子节点,sibling指向的是兄弟节点;如下以此JSX代码为例
