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节点。当后续这些元素关联的变量发生改变时,它又是怎样去触发更新的呢?

相关推荐
随逸17739 分钟前
《React 入门实战:从零搭建 TodoList》
react.js
Jing_Rainbow40 分钟前
【React-10/Lesson94(2026-01-04)】React 性能优化专题:useMemo & useCallback 深度解析🚀
前端·javascript·react.js
无巧不成书02181 小时前
React Native 深度解析:跨平台移动开发框架
javascript·react native·react.js·华为·开源·harmonyos
2301_796512522 小时前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:订单步骤条实践
javascript·react native·react.js·ecmascript·harmonyos
程序员酥皮蛋2 小时前
react 01 初学react
前端·javascript·react.js
全马必破三2 小时前
Vue 和 React 的区别
前端·vue.js·react.js
灵犀坠2 小时前
React+Node.js全栈实战:实现安全高效的博客封面图片上传(踩坑实录)
安全·react.js·node.js·router·query·clerk
无巧不成书02182 小时前
React Native 鸿蒙开发(RNOH)深度适配
前端·javascript·react native·react.js·前端框架·harmonyos
2301_796512522 小时前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:Tag 标签(通过 type 属性控制标签颜色)
javascript·react native·react.js·ecmascript·harmonyos
程序哥聊面试2 小时前
第一课:React的Hooks
前端·javascript·react.js