本文章是用来总结卡颂大佬的《从零实现 React18》课程的。
章节 1
主要讲解了一个项目的搭建应该从以下几个角度出发:
- 项目结构(是选择 Multi-repo 还是 Mono-repo)
- 打包工具
- 如何定义开发规范
章节 2
这一章主要讲了如何去实现 jsx 这个与宿主环境无关的方法,它在 react 包中。虽然是和宿主环境无关,但是这个方法是 react 中的基础,它会在运行时将已经转化后的 jsx 元素变为 ReactElement
章节 3 - 5
因为ReactElement是 React 中用来描述 jsx 中单一节点的数据结构,无法表达节点间的关系,且无法拓展(如:表达状态)。所以在Reconciler中还实现了FiberNode作为介于ReactElement和真实DOM间的虚拟DOM。然后实现workLoop的工作循环,而这一流程主要为beginWork、completeWork和commit.
JSX语法在编译时被 babel 编译为被编译成ReactElement,然后在beginWork阶段通过ReactElement生成FiberNode,最后在commit阶段将离屏DOM插入到 Continaer 中编程真正的DOM
在ReactDOM.render时创建fiberRootNode和rootFiber且beginWork流程中通过 diff 来对更新wip。并添加对应的flags。
然后在completeWork中将flags冒泡到父节点中,标记subtreeflags,为后续 commit 提供基础
在第四章中还实现了通用的更新机制Update和UpdateQueue,并在ReactDOM初始化时接入了这套更新机制,
不过目前并没有实现完整的 updateQueue 链表结构,只能支持单一 hook 的初始化和更新
章节 6
这一章节主要作用是实现commit操作,串联 Reconciler 逻辑与真实 DOM 操作。通过在completeWork中冒泡的flags,在完成所有子树的归的逻辑后,执行插入等 DOM 节点操作
而 commit 这个过程中会产生突变(Mutation),所谓Mutation就是将一个属性的值从 a 直接变为 b,比如 color: red -> color: green,而Mutation又被
分成了三个子阶段
- beforeMotation: 突变前
- mutation
- layout: 突变后
然后可以在这个Mutation的过程中执行副作用,
这章目前只实现了在mutation子阶段插入 DOM 节点和 Text 文本节点创建等基础操作。
并且后面用的useEffectLayouthook 就是在layout子阶段执行(目前未实现)
章节 7
通过在beginWork流程添加对函数组件的tag类型的判断,并实现renderWithHooks方法执行函数组件并获取函数组件的child对应的HostComponent来实现函数组件。
章节 8
通过实现Hook数据结构来管理状态,以链表的形式存储多个 hooks,并通过 next 指向下一个 hook ,
这也是为什么 react 强调函数组件内 hooks 的调用顺序不能变(定义 useState 等 hooks 只在函数组件的顶层定义,不要在条件中定义).
不同生命周期中的 hooks 集合不一样,通过实现内部数据共享层获取当前使用的 hooks 集合
章节 9
与逻辑无关,介绍了不同的源码调试方法以及 react 官方测试用例
章节 10
这一章节主要介绍了 update 流程中的 beginWork、completeWork 和 commitWork 流程。
在 beginWork 的reconciler流程中实现了了对单一节点和 text 节点的diff。
单节点通过key和type判断当前fiber是否可以复用,如果不能复用则会标记删除再创建。
文本节点是只要currentFiber.tag没有变化都会复用原来的 fiber 结构,只更新workInProgress.pendingProps。
然后在completeWrok阶段标记更新。最后在commitWork流程中添加了commitUpdate和commitDeleteion方法来分别对应Update和Deletion的副作用操作的执行
最后就是实现了 update 流程中的useStatehook, 实现updateWorkInProgressHook获取存放执行当前 hook 的全局变量workInProgressHook,
然后计算出新的 state。
章节 11
本章是针对浏览器宿主环境模拟实现的事件模型,主要模拟了浏览器事件捕获、冒泡流程,以及合成事件对象