我也是第一次解读react-dom 源码,有些地方不一定正确,望各位大佬指正,qq:1415009351
一、render解析
函数的执行流程思维脑图已经画出,大部分函数的功能说明文档也已经标明,这里主要梳理一下render执行的几个核心:(完整的函数说明文件都有,这里不再粘贴)
- legacyRenderSubtreeIntoContainer函数核心点
1.1传参
parentCompoent : null
children: element
container: container
forceHydrate: false 表示是否融合,用于区分客户端渲染和服务端渲染,render方法传false,hydrate方法传true
callback: callback(underfind)
forceHydrate 参数用来区分render还是hydrate即客户端渲染还是服务端渲染
1.2 首次渲染与再次渲染的流程问题
//首次渲染
// 对于首次挂载来说,更新操作不应该是批量的,所以会先执行unbatchedUpdates方法
// 该方法中会将executionContext(执行上下文)切换成LegacyUnbatchedContext(非批量上下文)
// 切换上下文之后再调用updateContainer执行更新操作
// 执行完updateContainer之后再将executionContext恢复到之前的状态
unbatchedUpdates(function () {
updateContainer(children, fiberRoot, parentComponent, callback);
});
//再次渲染
// 对于非首次挂载来说,是不需要再调用unbatchedUpdates方法的
// 即不再需要将executionContext(执行上下文)切换成LegacyUnbatchedContext(非批量上下文)
// 而是直接调用updateContainer执行更新操作
updateContainer(children, fiberRoot, parentComponent, callback);
2.fiber 架构
2.1fiber对象
FiberRoot.current = FiberNode
FiberNode.stateNode = FiberRoot
fiber对象的生成流程和参数意义文档都有这里不再描述,这里主要说说fiber对象的作用:
fiberRoot对象的作用:
- 整个react应用的起点
- 记录整个react应用更新过程中的各种信息
fiberNode 对象的作用:
1.每一个ReactElement对应一个Fiber对象
2.记录节点的各种状态
只有fiberNode 对象更新后,才会更新到classComponent上的this.state和this.props上
fiber 最终会生成链表,child和sibing属性指向第一个子节点和相邻的兄弟节点,return 指向父节点
2.2.updateQueue 更新队列
updateQueue也是一个链表,有first何last两个属性,指向定义一个和最后一个update对象,
2.3.fiber 与 updateQueue
每个fiber有一个属性updateQueue指向对应的更新队列,
每个fiber有一个属性alternate,开始指向自己的clone体,
update的变化会更新到alternate上,当更新完毕,altermate替换fiber
3.超时时间
expirationTime公式
var UNIT_SIZE = 10;
var MAX_SIGNED_31_BIT_INT = 1073741823;
var Sync = MAX_SIGNED_31_BIT_INT;
var Batched = Sync - 1;
var MAGIC_NUMBER_OFFSET = Batched - 1;
var initialTimeMs = Scheduler_now();
*/
function msToExpirationTime(ms) {
// 总是添加一个偏移量,这样我们就不会与NoWork的魔法数字冲突.
return MAGIC_NUMBER_OFFSET - (ms / UNIT_SIZE | 0);
}
var now = initialTimeMs < 10000 ? Scheduler_now : function () {
return Scheduler_now() - initialTimeMs;
};
function expirationTimeToMs(expirationTime) {
return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
}
这部分笔记可能有些局限,等后期setState流程看完之后再来补充fiber