網站首頁 編程語言 正文
Suspense和lazy()都是react中比較新的特性,在項目中使用還比較少,但是學習一下有助于在后面的項目中使用,同樣可以一窺React未來的發展方向
React.lazy()
概括
顧名思義lazy()方法是用來對項目代碼進行分割,懶加載用的.只有當組件被加載,內部的資源才會導入
為什么需要懶加載
在React的項目中import導入其他組件和庫都是默認在初始直接導入的,webpack等打包工具會將import導入的文件直接合并到一個大文件中,如果項目很大,打包完后初始化加載時需要加載的文件會很大,這時候就需要代碼分割
官方文檔中的例子
項目中:
// app.js
import { add } from './math.js';
console.log(add(16, 26)); // 42
// math.js
export function add(a, b) {
? return a + b;
}
打包后
function add(a, b) {
? return a + b;
}
console.log(add(16, 26)); // 42
如何進行代碼分割
在你的應用中引入代碼分割的最佳方式是通過動態 import() 語法,這是官方文檔中說的
動態import例子:
靜態導入:
import { add } from './math';
console.log(add(16, 26));
動態導入:
import("./math").then(math => {
? console.log(math.add(16, 26));
});
使用了動態導入之后,webpack檢測到這種語法會自動代碼分割,也就是壓縮到兩個文件里
React.lazy()就是對這個種動態導入方式的優化方法
使用:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
? return (
? ? // Displays <Spinner> until OtherComponent loads
? ? <React.Suspense fallback={<Spinner />}>
? ? ? <div>
? ? ? ? <OtherComponent />
? ? ? </div>
? ? </React.Suspense>
? );
}
發現沒有原來的動態導入寫法像 Promise的寫法鏈式調用,現在動態導入的方式,有點類似于Async寫出來是同步使用的,可以直接講返回的Promise對象作為組件使用,當這個組件pending是顯示的是Suspense中fallback的內容,只有resolve才顯示加載好的組件.
所以可以看出Suspense和React.lazy()需要結合在一起用,否則會報錯缺少Placeholder UI`
Suspense
Suspense的英文意思是懸念,懸停**,Suspense的作用就是在遇到異步請求或者異步導入組件的時候等待請求和導入完成再進行渲染,**相比普通的組件, 我們是要求render是一個純函數,一旦開始渲染不會等待,而有了Suspense后我們可以再render過程中寫一部代碼.
Suspense應用場景
Subspense存在兩種應用場景,第一種就是動態導入組件(如上),一種就是異步請求數據(暫時不支持,大概16.9版本)
動態導入組件
動態導入組件上面的例子就是上面的代碼片段,就是當這個組件pending是顯示的是Suspense中fallback的內容,只有resolve才顯示加載好的組件,所以fallback不能為空
優點
好處在于我們可以不用創建一些組件狀態的變量來控制是否顯示loading畫面和真正組件,這部分邏輯直接由Suspense內部實現. 而且還有一種場景就是當一個父組件中,有多個動態加載的組件,Suspense可以直接將loading狀態聚合,只有當所有組件加載完成才顯示,這里免去了復雜的邏輯判斷.
數據請求后渲染頁面
Suspense暫時還不支持數據請求后渲染, 預計是在16.9版本也就是2019年年中發布,但是以及有了實例使用的方法,下面這里就是官方的示例代碼,這里做一些翻譯解釋
// unstable_createResource這個就是一個封裝的請求數據的插件,不用太清楚類似于fetch
import {unstable_createResource} from 'react-cache';
// 聲明請求數據的方法
const TodoResource = unstable_createResource(fetchTodo);
//內部請求TodoResource.read(props.id) 就是異步請求數據
function Todo(props) {
? // Suspends until the data is in the cache
? const todo = TodoResource.read(props.id);
? return <li>{todo.title}</li>;
}
function App() {
? return (
? ? // 只有當兩個Todo內部的異步請求都完成后才能渲染出來,否則渲染<Spinner/>
? ? <React.Suspense fallback={<Spinner />}>
? ? ? <ul>
? ? ? ? {/* Siblings fetch in parallel */}
? ? ? ? <Todo id="1" />
? ? ? ? <Todo id="2" />
? ? ? </ul>
? ? </React.Suspense>
? );
}
這就是Suspense請求數據時的使用的方法,同樣解決了loading狀態的問題,相當于再render過程中加入了異步副作用操作,再普通的組件中異步操作是不起作用的,因為先渲染完,異步數據才會返回,這時候已經渲染完了.
Suspense實現原理
Subspense的實現主要就是利用了**ComponentDidCatch這個生命周期,這個什么周期就是用來捕獲子組件樹中的任何Javascript異常**
源碼就不分析了,這里說一下大概的流程步驟:
- 父組件渲染到子組件時發現異步請求,直接拋出錯誤,捕獲的結果是一個Promise對象
- ComponentDidCatch捕獲這個Promise對象,pending狀態下渲染fallback的
- 當resolve時重新render,遇到下一個異步請求重復上面操作
- 直到整個父組件的拋出的promise對象都為resolve,將loading替換為真正的組件.
總結
Suspense其實就是將原來放在外面處理的異步請求也就是副作用放到渲染過程中進行操作,這樣render這個函數就不再是純函數了,但是非常直觀方便,不需要再用很多狀態來控制loading顯示,而異步請求的結果無法預測會導致很多bug.
等到Suspense支持數據請求的場景時,我會考慮把它運用到自己的項目中, 感覺確實方便很多本來就覺得Loading狀態有點多余,雖然現在用的是Dva,會自動給effect創建loading狀態的,還不是特別需要.
原文鏈接:https://blog.csdn.net/deng1456694385/article/details/88999842
相關推薦
- 2023-03-05 Redis緩存工具封裝實現_Redis
- 2022-10-17 Go如何優雅的使用字節池示例詳解_Golang
- 2022-05-08 Python+matplotlib實現堆疊圖的繪制_python
- 2022-05-12 Kotlin any/none/all 函數
- 2022-02-02 ionic 禁止橫屏處理
- 2022-04-22 element的el-drawer預留操作欄問題
- 2022-02-16 向一組數組對象中,添加新的屬性值。和判斷這個數組對象中,某個屬性是否值都一樣
- 2022-09-29 淺談音視頻?pts?dts基本概念及理解_其它綜合
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支