写点什么

3.Fiber(我是在内存中的 dom)

用户头像
全栈潇晨
关注
发布于: 2021 年 02 月 17 日

人人都能读懂的 react 源码解析(大厂高薪必备)

3.Fiber(我是在内存中的 dom)

视频课程 &调试 demos

​ 视频课程的目的是为了快速掌握 react 源码运行的过程和 react 中的 scheduler、reconciler、renderer、fiber 等,并且详细 debug 源码和分析,过程更清晰。

​ 视频课程:进入课程

​ demos:demo

课程结构:

  1. 开篇(听说你还在艰难的啃react源码)

  2. react心智模型(来来来,让大脑有react思维吧)

  3. Fiber(我是在内存中的dom)

  4. 从legacy或concurrent开始(从入口开始,然后让我们奔向未来)

  5. state更新流程(setState里到底发生了什么)

  6. render阶段(厉害了,我有创建Fiber的技能)

  7. commit阶段(听说renderer帮我们打好标记了,映射真实节点吧)

  8. diff算法(妈妈再也不担心我的diff面试了)

  9. hooks源码(想知道Function Component是怎样保存状态的嘛)

  10. scheduler&lane模型(来看看任务是暂停、继续和插队的)

  11. concurrent mode(并发模式是什么样的)

  12. 手写迷你react(短小精悍就是我)

​ react15 在 render 阶段的 reconcile 是不可打断的,这会在进行大量 dom 的 reconcile 时产生卡顿,因为浏览器所有的时间都交给了 js 执行,并且 js 的执行时单线程。为此 react16 之后就有了 scheduler 进行时间片的调度,给每个 task 一定的时间,如果在这个时间内没执行完,也要交出执行权给浏览器进行绘制和重排,所以异步可中断的更新需要一定的数据结构在内存中来保存 dom 的信息,这个数据结构就是 Fiber(虚拟 dom)。

Fiber 的数据结构

Fiber 的自带的属性如下:

function FiberNode(  tag: WorkTag,  pendingProps: mixed,  key: null | string,  mode: TypeOfMode,) {  //保存节点的信息  this.tag = tag;//对应组件的类型  this.key = key;//key属性  this.elementType = null;//元素类型  this.type = null;//func或者class  this.stateNode = null;//真实dom节点
//连接成fiber树 this.return = null;//指向父节点 this.child = null;//指向child this.sibling = null;//指向兄弟节点 this.index = 0;
this.ref = null;
//用来计算state this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; this.dependencies = null;
this.mode = mode; //effect相关 this.effectTag = NoEffect; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null;
//优先级相关的属性 this.lanes = NoLanes; this.childLanes = NoLanes;
//current和workInProgress的指针 this.alternate = null;}

复制代码

Fiber 双缓存

​ 现在我们知道了 Fiber 可以保存真实的 dom,真实 dom 对应在内存中的 Fiber 节点会形成 Fiber 树,这颗 Fiber 树在 react 中叫 current Fiber,也就是当前 dom 树对应的 Fiber 树,而正在构建 Fiber 树叫 workInProgress Fiber,这两颗树的节点通过 alternate 相连.

function App() {  return (    <div>      xiao      <p>chen</p>    </div>  )}
ReactDOM.render(<App />, document.getElementById("root"));
复制代码



  • 在 mount 时:会创建 fiberRoot 和 rootFiber,然后根据 jsx 对象创建 Fiber 节点,节点连接成 current Fiber 树。


  • 在 update 时:会根据新的状态形成的 jsx(ClassComponent 的 render 或者 FuncComponent 的返回值)和 current Fiber 对比形(diff 算法)成一颗叫 workInProgress 的 Fiber 树,然后将 fiberRoot 的 current 指向 workInProgress 树,此时 workInProgress 就变成了 current Fiber。

​ 我们现在知道了存在 current Fiber 和 workInProgress Fiber 两颗 Fiber 树,Fiber 双缓存指的就是,在经过 reconcile(diff)形成了新的 workInProgress Fiber 然后将 workInProgress Fiber 切换成 current Fiber 应用到真实 dom 中,存在双 Fiber 的好处是在内存中形成视图的描述,在最后应用到 dom 中,减少了对 dom 的操作。

现在来看看 Fiber 双缓存创建的过程图

mount 时:

1.刚开始只创建了 fiberRoot 和 rootFiber 两个节点



2.然后根据 jsx 创建 workInProgress Fiber:



3.把 workInProgress Fiber 切换成 current Fiber



update 时:

1.根据 current Fiber 创建 workInProgress Fiber



2.把 workInProgress Fiber 切换成 current Fiber



发布于: 2021 年 02 月 17 日阅读数: 15
用户头像

全栈潇晨

关注

还未添加个人签名 2021.02.17 加入

还未添加个人简介

评论

发布
暂无评论
3.Fiber(我是在内存中的dom)