大家好,我是Kason。在本文中,我们将了解重构React内部的EffectsList机制的前因后果。阅读本文后,您可以掌握React18中Suspense特性与之前版本的差异和原因。欢迎加入人类优质前端框架群。副作用是什么?React的简单工作原理可以概括为:triggerupdaterenderstage:计算update引起的sideeffectcommitstage:executesideeffectInsertionandmovementPassive是指useEffect回调执行ChildDeletion是指移除childDOM节点等。更新引起DOM变化主要是因为Placement和ChildDeletion在起作用。那么render阶段如何保存sideeffects,commit阶段如何使用sideeffects呢?在重构EffectsList之前,在渲染阶段,会将有副作用的节点连接起来,形成一个链表,称为EffectsList。比如下图中,B、C、E有副作用,它们连接起来形成一个EffectsList:commit阶段不需要从A向下遍历整棵树,只需要遍历Effects列表找出所有有副作用的节点,并进行相应的操作。SubtreeFlags重构后,子节点的副作用会冒泡到父节点的SubtreeFlags属性中。例如B、C、E包含的sideeffects如下:冒泡过程如下:B的sideeffect是Passive,它冒泡到A,A.SubtreeFlags包含PassiveE的sideeffect,它冒泡到D,并且D.SubtreeFlags包含PlacementD。到C,C.SubtreeFlags包含Placement,C的副作用是Update,C.SubtreeFlags包含Placement,C冒泡到A最后A.SubtreeFlags包含Passive,Placement,Update,也就是说A的子树包含这三个side效果。在commit阶段,根据SubtreeFlags,逐层寻找有副作用的节点,并进行相应的操作。可以看出,SubtreeFlags需要遍历树,而EffectsList只需要遍历链表,效率更高。那么为什么要重构React呢?Suspense的回答是:虽然SubtreeFlags需要遍历比EffectsList更多的节点来遍历子树,但是React18中的一个新特性只是需要遍历子树。此功能是悬念。Suspense是v16中提供的功能,但是在v18之后,开启并发功能后,Suspense的行为与之前的版本有所不同。考虑以下组件:
