先附上流程图一张

先由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上, 这里需要注意一个点就是,uninitializedFiberstateNode的值是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实际上就代表了同步

在这里, 整理一下各个实例的关系,

 rootReactRoot实例,

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当成一个回调函数即可, 可以看到, rootFiberRoot实例被当成参数传入了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);
}

updateContainerAtExpirationTimecurrent(即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源码分析 第一篇的更多相关文章

  1. React Fiber源码分析 第二篇(同步模式)

    先附上两张流程图 1.scheduleRootUpdate  这个函数主要执行了两个操作  1个是创建更新createUpdate并放到更新队列enqueueUpdate, 1个是执行sheculeW ...

  2. React Fiber源码分析 (介绍)

    写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...

  3. jrtplib源码分析 第一篇 jthread的编译与分析

    第一篇 jthread的编译与分析 jrtplib代码依赖库jthread,因此先从jthread开始jrtplib的学习.首先从以下链接下载jthread的源代码http://research.ed ...

  4. React Fiber源码分析 第三篇(异步状态)

    先附上流程图~ 调用setState时, 会调用classComponentUpdater的enqueueSetState方法, 同时将新的state作为payload参数传进 enqueueSetS ...

  5. linux0.11内核源码剖析:第一篇 内存管理、memory.c【转】

    转自:http://www.cnblogs.com/v-July-v/archive/2011/01/06/1983695.html linux0.11内核源码剖析第一篇:memory.c July  ...

  6. JUC源码分析-集合篇:并发类容器介绍

    JUC源码分析-集合篇:并发类容器介绍 同步类容器是 线程安全 的,如 Vector.HashTable 等容器的同步功能都是由 Collections.synchronizedMap 等工厂方法去创 ...

  7. JUC源码分析-集合篇(十)LinkedTransferQueue

    JUC源码分析-集合篇(十)LinkedTransferQueue LinkedTransferQueue(LTQ) 相比 BlockingQueue 更进一步,生产者会一直阻塞直到所添加到队列的元素 ...

  8. JUC源码分析-集合篇(九)SynchronousQueue

    JUC源码分析-集合篇(九)SynchronousQueue SynchronousQueue 是一个同步阻塞队列,它的每个插入操作都要等待其他线程相应的移除操作,反之亦然.SynchronousQu ...

  9. JUC源码分析-集合篇(八)DelayQueue

    JUC源码分析-集合篇(八)DelayQueue DelayQueue 是一个支持延时获取元素的无界阻塞队列.队列使用 PriorityQueue 来实现. 队列中的元素必须实现 Delayed 接口 ...

随机推荐

  1. ADO.NET MSSSQLServer 操作简要总结

    1).数据库操作首先应该是链接,链接的方式有多种,不论怎样实现最终都是把链接字符串赋值给实现了 继承自DbConnection 类的SqlConnection类实例的ConnectionString属 ...

  2. rails应用的部署

    简单部署 RAILS_ENV=production rake secret /etc/profile export SECRET_KEY_BASE=刚才生成的密钥 source /etc/profil ...

  3. python猜数字GUI版本V0.1

    非常简单的GUI版猜数字游戏,后面有时间好好研究下 # -*- coding: utf-8 -*-"""Created on Mon Jan 28 16:30:17 20 ...

  4. POM文件详解(2)

    1      项目构建 <!-- 构建项目需要的信息 --> <build> <!-- 子项目可以引用的默认插件信息.该插件配置项直到被引用时才会被解析或绑定到生命周期. ...

  5. (三)Javascript面向对象编程:非构造函数的继承

    Javascript面向对象编程:非构造函数的继承   这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使 ...

  6. day_6深浅拷贝,元组字典集合类型定义和各种操作方法

    首先我们来讲一下深浅拷贝 1:值拷贝,假设一个列表等于L1 再定义一个L2=L1  这样就是值拷贝 L2只是存的L1存列表的地址,所以当L1发生改变,L2也随之改变 2:浅拷贝,L2=L1.copy( ...

  7. SSAS 内部错误:操作未能成功

    错误 -1056964601 : 内部错误: 操作未能成功,已终止. HY0008 是数据源的问题,设置数据源的虚拟连接就可以了

  8. IDEA环境下GIT操作浅析之二-idea下分支操作相关命令

    上次写到<idea下仓库初始化与文件提交涉及到的基本命令>,今天我们继续写IDEA环境下GIT操作之二--idea下分支操作相关命令以及分支创建与合并. 1.idea 下分支操作相关命令 ...

  9. Java 判断两个对象是否相等

    一.使用 == 与 equals == : 它的作用是判断两个对象的地址是不是相等.即,判断两个对象是不是同一个对象.(基本数据类型==比较的是值,引用数据类型==比较的是内存地址) equals() ...

  10. 2.抽取代码(BaseActivity)

    知识点 俩种退出程序的方法 复制集合 同步的用法 字符数组 工厂模式,生产fatgment,解决了碎片重复创建的问题 全局上下文 actionbar用法 fargmentadapter,当viewpa ...