react中的入口函数的模式

主要流程

主要函数执行过程

legacy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
render() =>
// 判断root 节点存不存在, 不存在
legacyRenderSubtreeIntoContainer() => {
legacyCreateRootFromDOMContainer() => {
// 首先ssr渲染相关逻辑
var shouldHydrate = forceHydrate || shouldXXXHeuristic(container);
// 中间代码... 然后
return createLegacyRoot(container, shouldHydrate? { hydrate: true } : undefined) => {
return new ReactDOMBlockingRoot(container, LegacyRoot, options) => {
// 创建根节点
this._internalRoot = createRootImpl(container, tag, options) => {
var root = createContainer(container, tag, hydrate) => {
return createFiberRoot(containerInfo, tag, hydrate) => {
var root = new FiberRootNode(containerInfo, tag, hydrate)
var uninitializedFiber = createHostRootFiber(tag)
root.current = uninitializedFiber
uninitializedFiber.stateNode = root
initializeUpdateQueue(uninitializedFiber)
return root
}
}
return root
}
}
}

}
}

创建Update对象

对于HostRoot或者ClassComponent会使用initializeUpdateQueue创建updateQueue,然后将updateQueue挂载到fiber节点上

1
2
3
4
5
6
7
8
9
10
11
12
function initializeUpdateQueue(fiber) {
var queue = {
baseState: fiber.memoizedState, //初始state,后面会基于这个state,根据Update计算新的state
firstBaseUpdate: null, //Update形成的链表的头
lastBaseUpdate: null, //Update形成的链表的尾
//新产生的update会以单向环状链表保存在shared.pending上,计算state的时候会剪开这个环状链表,
//并且连接在lastBaseUpdate后
shared: {pending: null},
effects: null
}
fiber.updateQueue = queue
}

然后我们进入updateContainer函数

updateContainer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function updateContainer(element, container, parentComponent, callback) {

// 获取update优先级
var lane = requestUpdateLane

// 创建update
var update = createUpdate(eventTime, lane)
// 就是jsx对象
update.payload = { element: element }
enqueueUpdate(current, update) // 生成换装链表
scheduleUpdateOnFiber(current, lane, eventTime)
return lane;
}

1
2
3
4
5
6
7
8
9
10
11
12
function createUpdate(eventTime, lane) {
// * 和 UpdateQueue 中的对象有些区别
var update = {
eventTime: eventTime,
lane: lane,
tag: UpdateState,
payload: null,
callback: null,
next: null
};
return update;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// enqueueUpdate

function enqueueUpdate(fiber, update) {

updateQueue = fiber.updateQueue;

sharedQueue = updateQueue.shared // 将要处理的update都会挂载在这个上面
pending = sharedQueue.pending

if(pending === null) {
update.next = update // 形成环状列表
} else {
update.next = pending.next
pending.next = update
}

sharedQueue.pending = update // 然后环状列表挂载在这里
}

scheduleUpdateOnFiber

1
2
3
4
5
6
function scheduleUpdateOnFiber(fiber, lane, eventTime) {
// 判断 lane 优先级
if (lane === SyncLane) { // 如果是同步Lane
performSyncWorkOnRoot(root)
}
}

concurrent

起点 createRoot

创建根节点

1
2
3
4
5
6
function createRoot(container, options) => {
return new ReactDOMRoot(container, options) => {
// 接下来的逻辑和legacy一样
this.internalRoot = createRootImpl(container, ConcurrentRoot, options)
}
}

ReactDOMRoot.prototype.render

1
2
3
4
5
6
ReactDOMRoot.prototype.render = ReactDOMBlockingRoot.prototype.render = function (children) => {
var root = this.internalRoot

// 主要调用
updateContainer(children, root, null, null) // updateContainer做的功能就和legacy模式一样
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function scheduleUpdateOnFiber(fiber, lane, eventTime) {
// ... 和上面一样 判断优先级 但此处 lane 不为 SyncLane
if (lane === SyncLane) {//同步lane 对应legacy模式
//...
performSyncWorkOnRoot(root);//render阶段的起点 render在地6章讲解
} else {//concurrent模式
//...
ensureRootIsScheduled(root, eventTime);//确保root被调度
}
ensureRootIsScheduled(root, currentTme) => {

//...
var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); //计算nextLanes
//...

if (nextLanes === NoLanes) {
// 判断 nextLanes 优先级
}
// 判断调度函数优先级是不是等于
if (newCallbackPrPriority === SyncLanePriority) {
// 直接调用回调
scheduleCallback(performSyncWorkOnRoot.bind(null, root))
} else if (newCallbackPrPriority === S yncBatchedLanePriority) {
// 用 ImmediatePriority 的优先级来调度我们的回调
scheduleCallback(ImmediatePriority$1, performSyncWorkOnRoot.bind(null, root))
} else {
var schedulerPriorityLevel = lanePriorityToSchedulerPriority(newCallbackPrPriority) // 把lane优先级转换成schedule优先级
//以schedulerPriorityLevel的优先级执行performConcurrentWorkOnRoot 也就是concurrent模式的起点
scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root))
}
}
}

两种模式的不同点

  • createRootImpl中传入的第二个参数不一样 一个是LegacyRoot一个是ConcurrentRoot
1
2
3
4
5
6
7
create(container, tag, options)

// ReactRootTags.js
export type RootTag = 0 | 1 | 2
export const LegactRoot = 0
export const BlockingRoot = 1
export const ConcurrentRoot = 2
  • requestUpdateLane中获取的lane的优先级不同
  • 在函数scheduleUpdateOnFiber中根据不同优先级进入不同分支,legacy模式进入performSyncWorkOnRoot,concurrent模式会异步调度performConcurrentWorkOnRoot