实现 render 函数 - 初始化更新队列

接下来,需要实现 render 函数,进行第一次挂载。

jsx 复制代码
const element = (
  <h1>
    hello <span>test</span> children
  </h1>
);

const root = createRoot(document.getElementById("root"));
root.render(element);

由之前的文章可知,root 是一个 ReactDOMRoot 实例。所以直接在 ReactDOMRoot 原型上添加 render 方法。

render 复制代码
// 注意 children 为传入的虚拟DOM 即 element
ReactDOMRoot.prototype.render = function (children) {
  // 这个 root 是 FiberRootNode 实例
  const root = this._internalRoot;
  // 更新容器
  updateContainer(children, root);
};

再回忆一下 HostRootFiberFiberRootNode

由于是初次渲染,所以第一次处理 HostRootFiber 的更新队列。

updateContainer 复制代码
/**
 * 更新容器 把虚拟DOM 变成真实DOM 插入容器
 * @param {*} element 虚拟DOM
 * @param {*} container 容器 FiberRootNode
 * @returns
 */
export function updateContainer(element, container) {
  // HostRootFiber 根 fiber
  const current = container.current;
  // 创建更新
  const update = createUpdate(eventTime, lane);
  // 需要更新的虚拟DOM
  update.payload = { element };
  // 添加更新
  // 返回根节点
  const root = enqueueUpdate(current, update);
  scheduleUpdateOnFiber(root);
}

更新队列的结构

initialUpdateQueue 可以看出,HostRootFiberupdateQueue 的结构为一个对象,对象中有个 shared 属性, shared 中有个 pending 属性指向循环链表。

updateQueue 复制代码
export function initialUpdateQueue(fiber) {
  const queue = {
    shared: {
      pending: null, // 循环链接,指向链表中最后一个 update
    },
  };
  fiber.updateQueue = queue;
}

由图可知,pending 永远指向循环链表中最后一个元素。由此可以实现 enqueueUpdate 函数。

enqueueUpdate 复制代码
export function enqueueUpdate(fiber, update) {
  const updateQueue = fiber.updateQueue;
  const sharedQueue = updateQueue.shared;
  const pending = sharedQueue.pending;
  if (pending === null) {
    // 第一次入队,指向自己
    update.next = update;
  } else {
    // 当队列不为空,新入的更新指向第一个更新
    update.next = pending.next;
    // pending 指向链表末尾
    pending.next = update;
  }
  // 指向最后一个 update
  sharedQueue.pending = update;
  // 找到根节点并返回
  return markUpdateLaneFromFiberToRoot(fiber);
}

执行 enqueueUpdate 后便生成了更新队列。

需要注意的是,当前更新中有一个 payload 参数,值为虚拟 DOM。

相关推荐
人工智能训练18 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪18 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
2601_9495936519 小时前
基础入门 React Native 鸿蒙跨平台开发:模拟智能音响
react native·react.js·harmonyos
xiaoqi92219 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin12332220 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头882121 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas13621 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠21 小时前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6
珑墨1 天前
【Turbo】使用介绍
前端
军军君011 天前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three