JSX如何转成react-fiber的?

什么是fiber?

一个fiber本质上是一个Fiber类的实例,以下是实例中的各个属性。可以看出,每一个Fiber节点之间通过指针相互关联,并找到下一个Fiber节点。因此,所有的Fiber节点相互关联就形成了Fiber树。

kotlin 复制代码
// 静态 Instance

this.tag = tag  //组件类型
this.key = key 
this.elementType = null  //和type大部分时间相同,除非使用react.memo包裹函数
this.type = null //和elementType大部分时间相同
this.stateNode = null  // 对应真实dom节点

// Fiber  //链表关系
this.return=null // 关联父节点
this.child=null // 关联子节点
this.sibling=null // 关联兄弟节点
this.index=0 // 同级fiber节点,代表它们插入dom的索引

this.ref = null // 字面意思,就是ref

/*------------------------作为动态单元的属性---------------------------*/

this.pendingProps = pendingProps
this.memoizedProps = null
this.updateQueue = null
this.memoizeState = null
this.dependencies = null

this.mode = mode

// Effects // 名称中带有effect的和副作用相关,
this.effectTag = NoEffect
this.subtreeTag = NoSubtreeEffect
this.deletions = null
this.nextEffect = null

this.firstEffect = null
this.lastEffect = null

this.lanes = NoLanes // 和优先级调度有关
this.childLanes = NoLanes

this.alternate = null // 与fiber架构的双缓存机制有关

Fiber节点是如何产生的呢?

Fiber树的产生源自于JSX模板,如以下代码:

假设我们有一个简单的 React 函数组件 ExampleComponent

javascript 复制代码
function ExampleComponent() {
  return (
    <div className="container">
      <h1>Hello, World!</h1>
      <p>This is an example component.</p>
    </div>
  );
}

首先,webpack编译时,Babel将其转化为普通的JS代码,在这里,React.createElement的三个参数:元素类型、属性对象和子元素。

jsx 复制代码
function ExampleComponent() {
  return React.createElement(
    'div',
    { className: 'container' },
    React.createElement('h1', null, 'Hello, World!'),
    React.createElement('p', null, 'This is an example component.')
  );
}

React.createElement做了什么事情呢?

React.createElement() 是 React 中用于创建虚拟 DOM 元素的函数。它接收三个参数:类型、属性对象和子元素,然后返回一个描述该元素的 JavaScript 对象

javascript 复制代码
function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map(child =>
        typeof child === "object" ? child : createTextElement(child)
      )
    }
  };
}

function createTextElement(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: []
    }
  };
}

上述代码是一个简化版的示例,实际的 React.createElement() 实现还包含其他功能,例如处理 keyref 等特殊属性,以及一些性能优化。以下是编译后的产物,可以认为是vNode

json 复制代码
{
  "type": "div",
  "props": {
    "className": "container",
    "children": [{
      "type": "h1",
      "props": {
        "children": [{
          "type": "TEXT_ELEMENT",
          "props": {
            "nodeValue": "Hello, World!",
            "children": []
          }
        }]
      }
    }, {
      "type": "p",
      "props": {
        "children": [{
          "type": "TEXT_ELEMENT",
          "props": {
            "nodeValue": "This is an example component.",
            "children": []
          }
        }]
      }
    }]
  }
}

vNode 转化为 Fiber 结构:

javascript 复制代码
// 定义 Fiber 对象
class Fiber {
  constructor(vNode) {
    this.type = vNode.type;
    this.props = vNode.props;
    this.key = vNode.key;
    this.child = null;
    this.sibling = null;
    this.alternate = null;
    // 其他需要用到的属性和状态
  }
}

// 构建 Fiber 树
function createFiberTree(vNode) {
  const fiber = new Fiber(vNode);

  if (vNode.children) {
    let prevChildFiber = null;
    vNode.children.forEach(childVNode => {
      const childFiber = createFiberTree(childVNode);
      if (prevChildFiber === null) {
        fiber.child = childFiber;
      } else {
        prevChildFiber.sibling = childFiber;
      }
      prevChildFiber = childFiber;
    });
  }

  return fiber;
}


// 将 vNode 转化为 Fiber 结构
const fiberTree = createFiberTree(vNode);

createFiberTree 函数用于递归构建 Fiber 树,根据 vNode 的层次结构创建相应的 Fiber 对象,并将子节点和兄弟节点连接起来。 生成的Fiber节点如下

javascript 复制代码
const exampleFiber = {
  type: "div",
  props: {
    className: "container",
  },
  child: Fiber { 
      type: 'h1', 
      props: { children: "Hello, World!" },
      key: null, 
      child: null, 
      sibling: Fiber { ... }, 
      alternate: null, 
  },
  sibling: null,
  return: null
};

exampleFiber.child = {
  type: "h1",
  props: { children: "Hello, World!" },
  child: null,
  sibling: null,
  return: exampleFiber
};

exampleFiber.child.sibling = {
  type: "p",
  props: { children: "This is an example component." },
  child: null,
  sibling: null,
  return: exampleFiber
};

在上述代码中,我们创建了两个子节点的 Fiber 对象,并将它们连接到父节点 exampleFiberchildsibling 属性上。通过这种方式,我们可以构建出一个简单的 Fiber 树结构。

在这里能得到的一个信息是,每一个元素都会变成一个Fiber节点。当后续这些元素关联的变量发生改变时,它又是怎样去触发更新的呢?

相关推荐
screct_demo9 小时前
詳細講一下在RN(ReactNative)中,6個比較常用的組件以及詳細的用法
javascript·react native·react.js
光头程序员17 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
limit for me17 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者17 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
VillanelleS21 小时前
React进阶之高阶组件HOC、react hooks、自定义hooks
前端·react.js·前端框架
傻小胖21 小时前
React 中hooks之useInsertionEffect用法总结
前端·javascript·react.js
flying robot1 天前
React的响应式
前端·javascript·react.js
GISer_Jing2 天前
React+AntDesign实现类似Chatgpt交互界面
前端·javascript·react.js·前端框架
智界工具库2 天前
【探索前端技术之 React Three.js—— 简单的人脸动捕与 3D 模型表情同步应用】
前端·javascript·react.js
我是前端小学生2 天前
我们应该在什么场景下使用 useMemo 和 useCallback ?
react.js