zoukankan      html  css  js  c++  java
  • 原理篇: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

    更新

    重复上述第二和第三步。

    四 两大阶段: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
  • 相关阅读:
    使用Fiddler模拟客户端http响应
    Vim显示行号
    Convert int to byte array
    bare linefeeds received in ASCII mode
    Memory Analyse Tool
    what is the difference between static and normal variables in c++
    Looper Could not create wake pip
    Convert Java Doc to CHM using jd2chm
    ARM(RISC)和x86(CISC)的技术差异
    处理器架构——从RISC与CISC到x86、ARM、MIPS
  • 原文地址:https://www.cnblogs.com/renzhiwei2017/p/15761309.html
Copyright © 2011-2022 走看看