suspense 和 lazy 配合实现懒加载的原理浅析
先看下面这段代码
// lazy.js
function Fn() {
return <div className="App">
函数组件
</div>
}
// app.js
// 添加一个固定的延迟时间,以便你可以看到加载状态
function delayForDemo(promise) {
return new Promise(resolve => {
setTimeout(resolve, 5000);
}).then(() => promise);
}
const LazyFn = lazy(() => delayForDemo(import('./lazy.js')));
function SuspendedApp() {
return (
<Suspense fallback={<div>加载中。。。</div>}>
<LazyFn />
</Suspense>
)
}
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(
<SuspendedApp />
);
这段代码模拟了懒加载的过程,运行之后,屏幕上会先展示 Suspense 的 fallback—— 加载中。。。 过 5 秒钟加载到组件后会自动重新渲染屏幕上出现 函数组件。。。。那这个 React 是怎么实现的呢,下面我们来看看实现的流程。
实现流程
这个流程发生在 Render 阶段。
以上就是主要的实现流程(当然实际会比上面介绍的复杂一点)。
源码环节
先是 Suspense 执行 beginWork
这里就是通过 Didcaptrue 来判断 showFallback 的值的。
第一次执行 showFallback 为 false ,因此先正常展示子节点
之后会处理 OffscreenComponent,
完了才会处理 lazy 组件,这个方法里最关键的就是 init 方法
也是在 init 方法里面抛出了异常
接下来是捕获异常,先是被beginWork 捕获,再抛出,最终被 renderRootSync 函数的错误处理捕获处理
接下来重新处理 Suspense,此时showFallback 为 true,同时处理了子节点和 Fallback 节点,最终返回Fallback节点,并渲染
接下来Promise被解决
再次处理 Suspense,更新子节点
然后处理 OffscreenComponent,再处理 lazy 节点
然后就是正常的渲染流程了,流程结束 懒加载的组件 替换 fallback 展示到页面上
最后
以上就是我梳理的 suspense 和 lazy 组合的工作流程,感谢大家的阅读,有不对的地方也欢迎大家指出来。
参考
- React 18.2.0 源码
转载自:https://juejin.cn/post/7261235534663778341