日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
給女朋友講React18新特性:startTransition

大家好,我是卡頌。

專注于為中小企業(yè)提供成都網(wǎng)站制作、做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)惠州免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了1000多家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

我女友是個(gè)鐵憨憨,又菜又愛(ài)玩。

她問(wèn)我:“卡卡,你說(shuō)時(shí)光真的可以重來(lái)?命運(yùn)真是可以選擇的么?”

我:“可以的,React18的新特性startTransition就行?!?/p>

startTransition的出現(xiàn)當(dāng)然不是為了逆轉(zhuǎn)命運(yùn),而是為了逆轉(zhuǎn)React的更新流程。

"在聊startTransition的具體應(yīng)用場(chǎng)景前,我先來(lái)聊聊React是如何揚(yáng)長(zhǎng)避短的。"

編譯時(shí)的短,運(yùn)行時(shí)的長(zhǎng)

如果我們用「重編譯時(shí)還是運(yùn)行時(shí)」區(qū)分前端框架。那么Vue和Svelte就是「重編譯時(shí)」的杰出代表。

在「編譯時(shí)」,這兩個(gè)框架可以分離模版語(yǔ)法中「變」與「不變」的部分,減少運(yùn)行時(shí)的代碼邏輯。

而React由于使用JSX(而非模版語(yǔ)法)描述視圖,走的是「重運(yùn)行時(shí)」的路線。

  • 不是React不想在「編譯時(shí)」做優(yōu)化,奈何JSX實(shí)在太靈活,做不到啊......

所以他的優(yōu)化策略也都是偏「運(yùn)行時(shí)」。

在「運(yùn)行時(shí)」,最大的開(kāi)銷是:狀態(tài)更新到視圖變化中間的計(jì)算步驟。

這個(gè)步驟是通過(guò)「遍歷Fiber樹(shù)」實(shí)現(xiàn)的。

常規(guī)的「運(yùn)行時(shí)優(yōu)化策略」,比如:

  • React.memo
  • PureComponent
  • shouldComponentUpdate

優(yōu)化方向都是:減少遍歷時(shí)需要遍歷的Fiber節(jié)點(diǎn)數(shù)量。

雖說(shuō)性能優(yōu)化的收益可以積少成多,但是React團(tuán)隊(duì)早已不滿足這種局部的小優(yōu)化。

性能優(yōu)化新思

路他們的思路是:

不同更新觸發(fā)的視圖變化顯然是有輕重緩急的。

如果能區(qū)分更新的優(yōu)先級(jí),讓高優(yōu)更新對(duì)應(yīng)的視圖變化先渲染,那么就能在設(shè)備性能不變的情況下,讓用戶更快看到他們想看到的UI。

比如:對(duì)于這樣一個(gè)搜索下拉框:

用戶期望:輸入框輸入的內(nèi)容要實(shí)時(shí)反映在視圖上(表現(xiàn)為輸入內(nèi)容不能卡頓)。

而結(jié)果下拉框的展示是可以有延遲的。

基于以上邏輯,React希望提供一個(gè)API,讓用戶告訴自己,哪些更新是「高優(yōu)」的,哪些是「低優(yōu)」的。

這樣,React就能知道優(yōu)先渲染誰(shuí)了。

這個(gè)API,就是startTransition。

startTransition的使用

接下來(lái),我們用一個(gè)Demo[1]演示startTransition的使用。

這個(gè)Demo會(huì)渲染一棵「畢達(dá)哥拉斯樹(shù)」。

拖動(dòng)左邊滑塊會(huì)改變樹(shù)渲染的節(jié)點(diǎn)數(shù)量。

拖動(dòng)頂部滑塊會(huì)改變樹(shù)的傾斜角度。

最頂上有個(gè)幀雷達(dá),可以實(shí)時(shí)顯示更新過(guò)程中的掉幀情況。

當(dāng)不點(diǎn)擊Use startTransition按鈕,拖動(dòng)頂上的滑塊。

可以看到:拖動(dòng)并不流暢,頂上的幀雷達(dá)顯示掉幀(出現(xiàn)黃色、紅色扇面)

當(dāng)點(diǎn)擊Use startTransition按鈕,拖動(dòng)頂上的滑塊。

可以明顯看到:拖動(dòng)變流暢,頂上的幀雷達(dá)顯示掉幀的情況變少

讓我們節(jié)選Demo的代碼看看,究竟發(fā)生了什么。

Demo都做了什么?

首先,控制滑塊、樹(shù)傾斜角度、要渲染的節(jié)點(diǎn)數(shù)量是分離在不同state中的:

 
 
 
 
  1. // 左側(cè)滑塊的state 
  2. const [treeSizeInput, setTreeSizeInput] = useState(8); 
  3. // 控制渲染節(jié)點(diǎn)數(shù)量的state 
  4. const [treeSize, setTreeSize] = useState(8); 
  5.  
  6. // 頂部滑塊的state 
  7. const [treeLeanInput, setTreeLeanInput] = useState(0); 
  8. // 控制樹(shù)傾斜角度的state 
  9. const [treeLean, setTreeLean] = useState(0); 
  10.  
  11. // startTransition的hook版本 
  12. const [isLeaning, startTransition] = useTransition(); 

當(dāng)拖動(dòng)頂上的滑塊(改變樹(shù)的傾斜角度)會(huì)調(diào)用changeTreeLean方法:

 
 
 
 
  1. function changeTreeLean(event) { 
  2.     const value = Number(event.target.value); 
  3.     setTreeLeanInput(value); // update input 
  4.  
  5.     // update visuals 
  6.     if (enableStartTransition) { 
  7.         startTransition(() => { 
  8.             setTreeLean(value); 
  9.         }); 
  10.     } else { 
  11.         setTreeLean(value); 
  12.     } 

該方法會(huì)改變兩個(gè)state:

  • 通過(guò)調(diào)用setTreeLeanInput改變頂部滑塊位置相關(guān)的state —— treeLeanInput
  • 通過(guò)調(diào)用setTreeLean改變樹(shù)的傾斜角度相關(guān)的state —— treeLean

是否點(diǎn)擊Use startTransition按鈕的區(qū)別,就在于setTreeLean是否會(huì)被作為startTransition的回調(diào)執(zhí)行:

 
 
 
 
  1. // 是否開(kāi)啟startTransition 
  2. if (enableStartTransition) { 
  3.   startTransition(() => { 
  4.     setTreeLean(value); 
  5.   }); 
  6. } else { 
  7.   setTreeLean(value); 

當(dāng)作為startTransition的回調(diào)執(zhí)行時(shí),setTreeLean改變的狀態(tài)(treeLean)對(duì)應(yīng)的視圖變化(即:改變樹(shù)的傾斜角度)會(huì)被視為「低優(yōu)先級(jí)的更新」。

即使其與改變滑塊狀態(tài)的方法(setTreeLeanInput)在同一上下文中執(zhí)行,

由于其優(yōu)先級(jí)較低,React會(huì)優(yōu)先處理「改變滑塊狀態(tài)」對(duì)應(yīng)的視圖變化。

表現(xiàn)為:滑塊的滑動(dòng)不卡頓。

startTransition的原理

鐵憨憨:“這么酷炫的功能實(shí)現(xiàn)起來(lái)一定很復(fù)雜吧?”

“恰恰相反,依賴于React底層實(shí)現(xiàn)的優(yōu)先級(jí)調(diào)度模型,startTransition的實(shí)現(xiàn)其實(shí)很簡(jiǎn)單!”

以剛才的代碼為例,如果加上console.log打?。?/p>

 
 
 
 
  1. console.log(1); 
  2. startTransition(() => { 
  3.   console.log(2); 
  4.   setTreeLean(value); 
  5. }); 
  6. console.log(3); 

那么會(huì)依次輸出:123

startTransition做的事情很簡(jiǎn)單,類似這樣:

 
 
 
 
  1. let isInTransition = false 
  2.  
  3. function startTransition(fn) { 
  4.   isInTransition = true 
  5.   fn() 
  6.   isInTransition = false 

也就是說(shuō),當(dāng)調(diào)用startTransition,在其上下文中獲取到的全局變量isInTransition為true。

如果startTransition的回調(diào)函數(shù)fn中包含更新?tīng)顟B(tài)的方法(比如上文Demo中的setTreeLean),

那么這次更新就會(huì)被標(biāo)記為isTransition,類似這樣:

 
 
 
 
  1. // 調(diào)用setTreeLean后會(huì)執(zhí)行的方法(偽代碼) 
  2. function setState(value) { 
  3.   stateQueue.push({ 
  4.     nextState: value, 
  5.     isTransition: isInTransition 
  6.   }) 

代表這是一個(gè)低優(yōu)先級(jí)的過(guò)渡更新。

接下來(lái),就是React內(nèi)部的調(diào)度、批處理與更新流程了。

  • 批處理的邏輯見(jiàn)給女朋友講React18新特性:Automatic batching

總結(jié)

今天,我們講了:

  • React為了彌補(bǔ)自身弱編譯時(shí)的缺點(diǎn),在運(yùn)行時(shí)作出的努力
  • startTransition本質(zhì)是讓開(kāi)發(fā)者手動(dòng)標(biāo)記更新的優(yōu)先級(jí)
  • startTransition的實(shí)現(xiàn)原理

鐵憨憨:”原來(lái)React為了性能優(yōu)化做了這么多努力,好復(fù)雜啊,我還是用Vue吧!“

我:“可不是嘛,React已經(jīng)在朝著實(shí)現(xiàn)一個(gè)瀏覽器的方向發(fā)展了?!?/p>

參考資料

[1]Demo:

https://swizec.com/blog/a-better-react-18-starttransition-demo/


名稱欄目:給女朋友講React18新特性:startTransition
文章地址:http://www.dlmjj.cn/article/cdjgghs.html