react-dom react 源码分析

399 阅读2分钟

分析render画的思维脑图,点击下载

我也是第一次解读react-dom 源码,有些地方不一定正确,望各位大佬指正,qq:1415009351

一、render解析

函数的执行流程思维脑图已经画出,大部分函数的功能说明文档也已经标明,这里主要梳理一下render执行的几个核心:(完整的函数说明文件都有,这里不再粘贴)

  1. 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对象的作用:

  1. 整个react应用的起点
  2. 记录整个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