React Fiber源码分析 第一篇
先附上流程图一张

先由babel编译, 调用reactDOM.render,入参为element, container, callback, 打印出来可以看到element,container,callback分别代表着react元素、DOM原生元素,回调函数

render实际上调用的是 legacyRenderSubtreeIntoContainer函数
render: function (element, container, callback) {
return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
}
legacyRenderSubtreeIntoContainer 这个函数, 实际上是初始化了root, 并调用了root.render方法, 而root是由legacyCreateRootFromDOMContainer函数返回的
function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
var root = container._reactRootContainer;
if (!root) {
// 初始化root
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);// Initial mount should not be batched.
unbatchedUpdates(function () {
if (parentComponent != null) {
root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
} else {
// 调用root的render方法
root.render(children, callback);
}
});
} else {
......
}
}
从代码中看出, legacyCreateRootFromDOMContainer执行了两个操作, 一个是清除掉所有的子元素, 另外一个则是返回了一个 ReactRoot实例, 这里需要注意一点, root默认是同步更新的, 即isAsync 默认为false
function legacyCreateRootFromDOMContainer(container, forceHydrate) {
...// 清除所有子元素
if (!shouldHydrate) {
var warned = false;
var rootSibling = void 0;
while (rootSibling = container.lastChild) {
{
if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
warned = true;
}
}
container.removeChild(rootSibling);
}
}// 默认为同步状态
var isAsync = false;
return new ReactRoot(container, isAsync, shouldHydrate);
}
从ReactRoot中, 我们把createContainer返回值赋给了 实例的_internalRoot, 往下看createContainer
function ReactRoot(container, isAsync, hydrate) {
var root = createContainer(container, isAsync, hydrate);
this._internalRoot = root;
}
从createContainer看出, createContainer实际上是直接返回了createFiberRoot, 而createFiberRoot则是通过createHostRootFiber函数的返回值uninitializedFiber,并将其赋值在root对象的current上, 这里需要注意一个点就是,uninitializedFiber的stateNode的值是root, 即他们互相引用
function createContainer(containerInfo, isAsync, hydrate) {
return createFiberRoot(containerInfo, isAsync, hydrate);
}
function createFiberRoot(containerInfo, isAsync, hydrate) {
// 创建hostRoot并赋值给uninitiallizedFiber
var uninitializedFiber = createHostRootFiber(isAsync);
// 互相引用
var root = void 0;
root = {
current: uninitializedFiber,
...
};
uninitializedFiber.stateNode = root;
最后是返回了一个fiberNode的实例, 在这里我们可以看到mode这个字段, 由于在一开始就将isAsync初始化为false, 所以mode实际上就代表了同步
在这里, 整理一下各个实例的关系,
root为ReactRoot实例,
root._internalRoot 即为fiberRoot实例,
root._internalRoot.current即为Fiber实例,
root._internalRoot.current.stateNode = root._internalRoot
function createHostRootFiber(isAsync) {
var mode = isAsync ? AsyncMode | StrictMode : NoContext;
return createFiber(HostRoot, null, null, mode);
}
var createFiber = function (tag, pendingProps, key, mode) {
return new FiberNode(tag, pendingProps, key, mode);
};
function FiberNode(tag, pendingProps, key, mode) {
// Instance
this.tag = tag;
this.key = key;
this.type = null;
this.stateNode = null;
// Fiber
this.return = null;
this.child = null;
this.sibling = null;
this.index = 0;
...
}
初始化完成, 接下来就是root.render执行了, 在这里, 先暂时忽略ReactWork, 把work._onCommit当成一个回调函数即可, 可以看到, root即FiberRoot实例被当成参数传入了updateContsainer里面, 往下看updateContainer
ReactRoot.prototype.render = function (children, callback) {
var root = this._internalRoot;
var work = new ReactWork();
callback = callback === undefined ? null : callback;
if (callback !== null) {
work.then(callback);
}
updateContainer(children, root, null, work._onCommit);
return work;
};
updateContsainer里面使用了 currentTime 和 expirationTime,
currentTime是用来计算expirationTime,
expirationTime代表着优先级, 留在后续分析,
这里我们知道是同步更新 即 expirationTime = 1. 紧接着调用了updateContainerAtExpirationTime
function updateContainer(element, container, parentComponent, callback) {
var current$$1 = container.current;
var currentTime = requestCurrentTime();
var expirationTime = computeExpirationForFiber(currentTime, current$$1);
return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
}
updateContainerAtExpirationTime将current(即Fiber实例)提取出来, 并作为参数传入调用scheduleRootUpdate
function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) {
// TODO: If this is a nested container, this won't be the root.
var current$$1 = container.current;
...
return scheduleRootUpdate(current$$1, element, expirationTime, callback);
}
到了这里告一段落, scheduleRootUpdate接下来就是React新版本异步渲染的核心了, 留在下一篇继续解读
React Fiber源码分析 第一篇的更多相关文章
- React Fiber源码分析 第二篇(同步模式)
先附上两张流程图 1.scheduleRootUpdate 这个函数主要执行了两个操作 1个是创建更新createUpdate并放到更新队列enqueueUpdate, 1个是执行sheculeW ...
- React Fiber源码分析 (介绍)
写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...
- jrtplib源码分析 第一篇 jthread的编译与分析
第一篇 jthread的编译与分析 jrtplib代码依赖库jthread,因此先从jthread开始jrtplib的学习.首先从以下链接下载jthread的源代码http://research.ed ...
- React Fiber源码分析 第三篇(异步状态)
先附上流程图~ 调用setState时, 会调用classComponentUpdater的enqueueSetState方法, 同时将新的state作为payload参数传进 enqueueSetS ...
- linux0.11内核源码剖析:第一篇 内存管理、memory.c【转】
转自:http://www.cnblogs.com/v-July-v/archive/2011/01/06/1983695.html linux0.11内核源码剖析第一篇:memory.c July ...
- JUC源码分析-集合篇:并发类容器介绍
JUC源码分析-集合篇:并发类容器介绍 同步类容器是 线程安全 的,如 Vector.HashTable 等容器的同步功能都是由 Collections.synchronizedMap 等工厂方法去创 ...
- JUC源码分析-集合篇(十)LinkedTransferQueue
JUC源码分析-集合篇(十)LinkedTransferQueue LinkedTransferQueue(LTQ) 相比 BlockingQueue 更进一步,生产者会一直阻塞直到所添加到队列的元素 ...
- JUC源码分析-集合篇(九)SynchronousQueue
JUC源码分析-集合篇(九)SynchronousQueue SynchronousQueue 是一个同步阻塞队列,它的每个插入操作都要等待其他线程相应的移除操作,反之亦然.SynchronousQu ...
- JUC源码分析-集合篇(八)DelayQueue
JUC源码分析-集合篇(八)DelayQueue DelayQueue 是一个支持延时获取元素的无界阻塞队列.队列使用 PriorityQueue 来实现. 队列中的元素必须实现 Delayed 接口 ...
随机推荐
- U-Boot Makefile分析(5)主控Makefile分析
这次分析源码根目录下的Makefile,它负责读入配置过的信息,通过OBJS.LIBS等变量设置能够参与镜像链接的目标文件,设定编译的目标等等. HOSTARCH := $(shell uname - ...
- 代码文档生成工具Doxygen的使用备忘
Doxygen备忘 下载与安装 一般步骤 生成配置文件Doxyfile: doxygen (-s) -g 建立目录结构, 比如Doxyfile文件\doc文件夹(输出)\src文件夹(放代码) -&g ...
- arp脚本
1.什么是arp?arp可以解决什么问题? ARP:是地址解析协议 arp解决我们知道一个机器(主机或者路由器)的IP地址,需要找出其相应的硬件地址 2.编写ARP脚本,抓取对应主机的mac地址 1 ...
- PHP的生命周期:
- 学习C++后感
c++是一门系统级语言,记得大一是要学习这门课时还上网找过学习方法.但网上很多学习方法看的我都头晕,都说学习C++很难,有的说学C++前最好先学C语言,有的说学C++最好不要学C语言,当翻了C++课本 ...
- Project Structure详解
Project Structure “ 项目结构”对话框允许您管理项目和IDE级别的元素,例如Modules,Facets,Libraries, Artifacts和SDK. 在大多数情况下,左边部分 ...
- Dubbo 源码分析 - 自适应拓展原理
1.原理 我在上一篇文章中分析了 Dubbo 的 SPI 机制,Dubbo SPI 是 Dubbo 框架的核心.Dubbo 中的很多拓展都是通过 SPI 机制进行加载的,比如 Protocol.Clu ...
- 【洛谷3865】 【模板】ST表(猫树)
传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里
- Canal学习笔记(服务端)
canal服务端 canal服务端有两种运行模式,一种单机模式,一种HA运行模式(zk保证) 单机模式:同步的binlog节点信息保存在本地(/conf/{自定义分区文件夹}/),meta.dat H ...
- Android 图片高级绘图效果---高斯模糊
高斯模糊就是将指定像素变换为其与周边像素加权平均后的值,权重就是高斯分布函数计算出来的值.高斯模糊能够将图片制作成类似磨砂的图片效果,一般这些图片都用来作为背景. 目前使用到的是RenderScrip ...