ReactFiber在并发模式下的运行机制

本文深入探讨了ReactFiber在并发模式下的运行机制,包括React16的两个阶段:reconcile和commit,以及新添加的schedule阶段。在并发模式下,React通过调度算法决定组件的更新优先级。详细解析了从scheduleWork到completeRoot的流程,以及在commit阶段如何更新视图。还介绍了Suspense和懒加载的实现机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ReactFiber在并发模式下的运行机制

新一年又开始了,React过去一年悄悄实现了Suspense,带来了React Hooks ,源码也大变换了。因此好有必须重新阅读一下,看它是如何实现这些功能,及未来准备开放的并发渲染功能。

React16早期将原来的diff过程拆分成两个阶段,第一个阶段叫 reconcile , 也就是原来diff虚拟DOM的过程。这阶段有大量叫reconcileXXX的方法参与其中,如reconcileSingleElement、reconcileSinglePortal、reconcileChildFibers、reconcileSingleTextNode、 reconcileChildrenArray、reconcileChildrenIterator、 reconcileChildFibers...会创建组件实例与真实DOM节点,执行一些轻量钩子。第二个阶段叫commit,在并发模式下,可能多次reconcile才有一次commit。commit就是将水面下的效果浮现出来,比如将节点插入到DOM树,修复节点的属性样式文本内容,执行如componentDidXXX这样的重量钩子,执行ref操作(这时可能涉及DOM操作)。

schedule源码剖析

现在,React在这两个阶段之前新添加了一个阶段,schedule。因为一个页面可能有多个ReactDOM.render,虚拟DOM树中也通常存在多个拥有自更新能力的组件(React Hooks的出现让无状态组件也具有自更新能力)。在并发模式下,组件setState不会立即更新视图,于是在一个时间段中,就有多个待更新的组件,这些组件叫root(渲染的起点),但谁是真正的nextRoot呢?需要一个调度算法进行决定。React根据当前时间给每个组件分配一个过期时间(相当优先级),数字越大,就越优先执行。

schedule的起点方法是scheduleWork。 ReactDOM.render, setState,forceUpdate, React Hooks的dispatchAction都要经过scheduleWork。

scheduleWork里面有一个scheduleWorkToRoot方法,负责将当前fiber及其alternate的过期时间推迟(或者叫加大)。由于在ReactFiber中,过期时间等价于优先级,换言之,一个组件在某个时间段setState频繁,那么它就越优先更新。

在并发模式下,setState后33ms执行(如果在动画中,为了保证流畅,增长到100ms间隔 )。如果更新的节点是一个受控组件(input),那么它是直接进入interactiveUpdates方法,不经过scheduleWork,是立即更新!React还有一个没登记到文档batchedUpdates方法,它可以让一大遍节点立即更新,并且无视shouldComponentUpdate return false!!类似batchedUpdates这样的特权方法,在React16中已经存在了许多了!

 

上面是ReactFiber的总流程。最下面的绿色方法都是贵族方法,拥有极高的优先执行权。

//by 司徒正美 QQ 370262116
function scheduleWork(fiber, expirationTime) {
	const root = scheduleWorkToRoot(fiber, expirationTime);
	if (root === null) {
		return;
	}
	if (
		!isWorking &&
		nextRenderExpirationTime !== NoWork &&
		expirationTime > nextRenderExpirationTime
	) {
		resetStack();
	}
	markPendingPriorityLevel(root, expirationTime);
	if (
		//如果在准备阶段或commitRoot阶段或渲染另一个节点
		!isWorking ||
		isCommitting ||
		// ...unless this is a different root than the one we're rendering.
		nextRoot !== root
	) {
		const rootExpirationTime = root.expirationTime;
		requestWork(root, rootExpirationTime);
	}
}

requestWork是决定以什么方式进入performWorkOnRoot。有四种情况,一如果已经开始渲染,那么就立即返回,二是直接进入performWorkOnRoot, 三是先进入performSyncWork,然后到performSync到performWork到performWorkOnRoot,四是异步方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值