原理篇:fiber

一、Fiber基础

什么是fiber

fiber是react中最小的执行单位,可以理解为fiber就是虚拟DOM。

更新 fiber 的过程叫做 Reconciler(调和器)

element,fiber, DOM 之间的关系?

  • element 就是jsx语法,通过React.createElement创建成element对象.
  • DOM 就是浏览器的DOM
  • fiber:每一次的 element 变化都会通过 调和 fiber 来 触发真实 DOM 渲染。

image

fiber保存了哪些信息

function FiberNode(){

    ....

  this.key = key;                  // key调和子节点时候用到。 
  
  this.return = null;              // 指向父级fiber
  this.child = null;               // 指向子级fiber
  this.sibling = null;             // 指向兄弟fiber 
  this.index = 0;                  // 索引

  this.expirationTime = NoWork;    // 通过不同过期时间,判断任务是否过期, 在v17版本用lane表示。

  this.alternate = null;           //双缓存树,指向缓存的fiber。更新阶段,两颗树互相交替。
  
  ....
}

每一个 element 都会对应一个 fiber ,每一个 fiber 是通过 return , child ,sibling 三个属性建立起联系的。

  • return: 指向父级 Fiber 节点。
  • child:指向子 Fiber 节点。
  • sibling:指向兄弟 fiber 节点。

元素结构如下代码:

export default class Index extends React.Component{
   state={ number:666 } 
   handleClick=()=>{
     this.setState({
         number:this.state.number + 1
     })
   }
   render(){
     return <div>
       hello,world
       <p > 《React进阶实践指南》 { this.state.number } 👍  </p>
       <button onClick={ this.handleClick } >点赞</button>
     </div>
   }
}

fiber对应的关系如下:
image

二、Fiber更新机制

初始化

第一步:创建fiberRoot和rootFiber

  • fiberRoot: 首次构建应用, 创建一个 fiberRoot ,作为整个 React 应用的根基。
ReactDOM.render(<Index/>, document.getElementById('app'));
  • rootFiber: 通过 ReactDOM.render 渲染出来的。比如一个组件会渲染一个rootFiber。

rootFiber可以有多个,但fiberRoot只能有一个。

image

第二步:创建workInProgress树

  • workInProgress:内存中构建的 Fiber 树。
  • current:正在视图层渲染的树叫做 current 树。

渲染流程中,先复用current树(rootFiber)的alternate 作为 workInProgress。

image

第三步:深度调和子节点,渲染视图
遍历fiber树,以workInProgress 作为最新的渲染树,即current Fiber 树。

image

更新

重复上述第二和第三步。

总结:workInProgress是内存中构建的树,current是当前正在渲染的树,这两棵树通过alternate 指针相互关联,在下一次渲染的时候直接使用缓存树作为下次的渲染树

三 两大阶段:render和commit

render

render阶段主要涉及两个过程: beginWork 和 completeUnitOfWork。

beginWork

  • 执行部分生命周期和render,得到最新的 children
  • 向下遍历调和 children ,复用 oldFiber
  • 打不同的副作用标签effectTag,比如类组件的生命周期,或者元素的增加,删除,更新。

completeUnitOfWork
completeUnitOfWork 的流程是自下向上的

  • 将effectTag 的 Fiber 节点保存到 effectList 的单向链表中。 在 commit 阶段,将不再需要遍历每一个 fiber ,只需要执行更新 effectList 就可以了。
  • 处理组件的context,初始化元素标签,生成真实DOM,处理props,等

commit

commit 可以分为3个阶段:

  • Before mutation 阶段(执行 DOM 操作前);
  • mutation 阶段(执行 DOM 操作);
  • layout 阶段(执行 DOM 操作后)
  1. Before mutation
  • 对于类组件,执行 getSnapshotBeforeUpdate 生命周期
  • 对于函数组件,异步调用 useEffect
  1. Mutation
  • 进行真实的 DOM 操作
  1. Layout
  • 对于类组件,会执行setState的callback
  • 对于函数组件,会执行useLayoutEffect

备注:
本文学习总结自: 《React 进阶实践指南》

posted @ 2022-01-04 09:27  webLion200  阅读(652)  评论(0编辑  收藏  举报