close

👆點擊「博文視點Broadview」,獲取更多書訊

我莫名地發現自己坐在一座廟宇的大殿中,周圍的人有老有小、衣着各異,但似乎人人都眼神木訥、正襟危坐。

這是個什麼鬼地方?

我正四處打量,忽然有人輕輕敲擊我的後背,我轉過身去,看到一個大概二十出頭的女孩。她俏皮地笑了笑,把食指豎在唇前,示意我不要出聲。順着她手指的方向,透過前排的間隙,我向大殿中央望去。

只見那裡端坐一人,身披黃色錦袍,右手握着一支一米多長的碩大毛筆,正在面前的畫布上運筆如飛。

我想,敢情是網紅畫家現場表演?怪不得那麼多人圍觀。

忽然,一旁的助手將另一幅畫布放在黃衣人面前,他也不停筆,伸出另一隻手,用一支一模一樣的毛筆在新的畫布上開始作畫。

一心二用、左圓右方啊,有兩把刷子!你到底畫的是啥?

正尋思間,助手在黃衣人面前加了一幅畫布,只見他雙手仍然不停筆,竟從錦袍中伸出第三隻手,拿着毛筆在這第三幅畫布上作畫。

我確信沒看錯!他確實有三隻手,拿着三支筆!我驚魂未定,助手卻又拿出三幅畫布,盡數都擺在畫家面前。

難道他是三頭六臂?我不禁倒吸一口氣。

果不出所料,畫家又多出三隻手,六手六筆在六幅畫布上同時作畫,沒有絲毫地猶豫和停頓。

不過這次我看清楚了,他多餘的手並不是從錦袍里伸出來的,而是原來的手稍微晃動了一下,在虛影之中不知如何就「分裂」出一隻手來,拿着一支同樣的毛筆。

這是什麼情況?忙於對眼前的景象作出合理解釋,我的大腦差點宕機。

只見畫家微微點頭,最邊上的一隻手提筆輕輕一頓,似乎是完成了該幅畫作。那隻手微微晃動了一下,又是一陣虛影,竟然和旁邊的一隻手合而為一。

在我的瞠目結舌中,畫家另外的四隻手也紛紛完成畫作,虛影之下四合二、二合一,最後只留下形單影隻的右手。一陣清風拂過,錦袍空空的左袖隨風晃動。

畫家隨即將手中的畫筆凌空一擲,助手穩穩接住,雙手高舉過頭,朗聲道:「十八紀元,畫師登仙。」 我看見周圍眾人紛紛拜倒在地。

「其實他就是動作快而已,明明只有一隻手卻畫出了六隻手的效果。」 那女孩不知什麼時候擠到我身旁,悄聲告訴我。「快行禮啊,被畫師看見了可不好。」 我這才反應過來,忙不迭地模仿旁人的姿勢,但已經太晚。畫師目光如炬,早已注意到了我這個不和諧的音符,助手則右手運力,將毛筆如標槍一般朝我擲來。

我大驚之餘,急忙躲避,頭卻撞到旁邊不知什麼硬物,隨即發現自己正趴在家裡書桌上,並沒有什麼廟宇大殿。在我面前也並沒有什麼畫師,而只是電腦屏幕和一本書,封面上寫着《坐標 React 星:React 核心思維模型》。

我這才記起來,剛才是在趕一篇關於 React 18 的文章(剛剛發布的 React 最新版本),實在太累就趴在桌上休息了一會。我回想起剛才的夢境,看着桌上那本書,那是一本我剛剛整理完成的 React 教程,包含了很多這樣的故事橋段。我不禁笑了起來,這是入戲太深啊……

不過話說回來,這獨臂畫師跟 React 18 確實有很多相通之處。React 18 堪稱 React 發展史上的一個里程碑,它的核心是所謂的「並發渲染」(Concurrent rendering)。

React 18核心:並發渲染(Concurrent rendering)

什麼是並發渲染呢?這得從 React 18 之前版本的組件渲染機制說起。

React 渲染曾經是一個必須從頭到尾完整執行的過程,一旦開始渲染就不能中斷,要等到將界面效果呈現給用戶以後才能開始下一輪。

這意味着什麼呢?

我們知道 JavaScript 從本質上講是單線程的,React 運行在瀏覽器的主線程之上,在這個單一的線程上還有很多代碼排隊執行,包括了對用戶體驗至關重要的用戶輸入處理、頁面布局、動畫等等。如果 React 的渲染代碼執行時間太長,排在後面的其它代碼便無法及時運行。所以,當渲染複雜組件時,用戶界面常常會出現卡頓的現象。這好比要求我們的獨臂畫師必須完成一幅畫以後才可以做其他事,停下來喝口水都不行。

不過,現在到了十八紀元,動作奇快的畫師得以大顯神威。

在 React 18 里,組件渲染過程變得可以暫停、可以從斷點恢復、甚至可以丟棄一些過時中間結果,這樣,不管組件有多複雜,其渲染過程也不會阻塞主線程。React 可以在一個組件上先畫幾筆,這時如果有更高優先級的任務(例如處理用戶輸入),或者因為某種原因需要等待(例如下載數據),React 就暫停這個組件的渲染,轉而處理其他任務,在某個時刻再回過頭來繼續渲染原來的組件,因為切換的速度很快,從宏觀上看來就是三頭六臂、多個任務同時執行了!

(圖片來源:Beebee老師)

並發渲染聽起來很強大吧?那麼作為開發者,我們怎麼才能用到它的三頭六臂呢?

事實上,並發渲染並非面向應用開發者的 API,它是 React 18 的底層工作機制,算是一種實現細節。不過,它是 React 18中(以及未來版本)很多新功能的基礎。理解了並發渲染的工作原理,我們將會更加得心應手,所以我才在它上面花了這麼長的篇幅。

下面挑兩個 React 18 中最典型的新功能為你簡略介紹一下,它們分別是——Transition 和 Suspense。

Transition

Transition 相關 API 的目標是無縫支持不同配置的運行環境,旨在消除用戶界面在慢速機器上的卡頓,而在高性能環境中又能充分地利用計算資源、快速更新界面和顯示更豐富的內容。

為了達到上述目標,React 18 需要我們幫助區分緊急和非緊急的界面更新。

所謂緊急更新,是指那些直接銜接用戶交互的界面更新,例如顯示鍵盤輸入內容、鼠標點擊反饋等等。如果此類界面更新沒有得到及時處理,哪怕只是延遲了幾百毫秒,用戶就會感到很明顯的卡頓。

而非緊急更新則是指那些即使是延遲處理也不會讓人感到意外的界面更新,例如,根據下載的數據顯示圖表,即使慢個幾秒問題也不大,此類更新也被稱為 Transition。

正是因為並發渲染,React 可以「不緊不慢地」運行非緊急更新,而當用戶輸入到來時暫停手上的工作並立即處理緊急更新。這樣,我們既在慢速機器上保證了界面的響應速度,又能在高性能環境中快速更新界面、顯示更豐富的內容。類似的需求如果要「手工」來實現將會相當麻煩,效果還不一定理想。而在 React 18 里,我們只需要標記好非緊急更新,具體的更新速度和顯示內容由 React 根據機器速度自動調節,對於開發者來說是完全透明的。

那麼,怎麼標記非緊急更新呢?

React 提供了一個 startTransition 函數(另外還有一個 useTransition Hook,用法類似,在此略去):

startTransition( () => { // 在此處放入非緊急更新,如 setData(...)。凡是不在此的更新均默認為緊急更新。})

如下是一個 Slider 組件的示例:

function FastSlider({ onChange }) { const [value, setValue] = useState(1); return ( <input type="range" value={value} onChange={(e) => { const v = e.target.valueAsNumber; setValue(v); // ==> 這是緊急更新,因為是對用戶輸入的反饋 startTransition(() => onChange(v)); // 這是非緊急更新,放到 startTransition 函數裡讓 React 「慢慢」執行。 }} /> );}

所以,標記非緊急更新是很容易的,放到 startTransition 調用里就行了。React 將默認其它的更新為緊急更新。

Suspense

Suspense 是 React 18 提供的一個組件,可以用來以聲明式的方式定義進度信息。具體用法見如下代碼:

function MyComponent() { return ( <Suspense fallback={<div>努力加載中...</div>}> <ComponentThatLoadsData /> </Suspense> )}

在上述代碼里,當 ComponentThatLoadsData 開始下載數據時,對於該組件的渲染過程就會暫停(Suspend),Suspense 組件將接管並渲染 fallback 中的進度信息。

此時,用戶將在瀏覽器中看到「努力加載中...」。等到數據下載完成,React 將繼續渲染 ComponentThatLoadsData,顯示最終結果。跟 Transition 類似,同樣是並發渲染的三頭六臂在這裡起到了至關重要的作用。

你可能會問,用這種方式定義進度條到底有什麼優勢呢?以前用一個 loading state 加條件渲染的方式不是挺好嗎?

這一點以後有時間我再撰文詳述。

簡言之,Suspense 將所有異步操作的這一部分邏輯抽象出來,把等待狀態作為 JSX 里的「一等公民」,這樣便於實現開發、設計工具支持,以及與設計師合作。畢竟,React 是以全面提高用戶體驗為目標的,與整個開發生態系統的協作是很重要的。

另外,React 18 中的 Suspense 在服務器端也有良好支持。同樣是得益於並發渲染,服務器能夠以流(stream)的方式為客戶端提供渲染結果,這樣就完美支持了包含異步操作的組件的 服務器端渲染(Server-side Rendering,SSR)。服務器能夠先渲染組件的一部分,將包含進度信息的頁面提供給客戶端,等到暫停的組件準備就緒再提供剩餘的渲染結果。

總結

React 18 以及畫師的故事就講到這裡了。並發渲染是 React 前進的一大步,是 React 核心開發團隊歷經多年的研究、實驗和開發的成果。我認為其必將對 React 以及整個前端開發領域的發展起到意義深遠的作用。

不過,如果你還是 React 新手,是不是覺得有太多東西需要學了?什麼組件、渲染,又加上 Transition、Suspense…… 告訴你一個好消息,你可以完全暫時不用管上面的代碼和技術細節,記住獨臂畫師的六隻手就夠了。等到你掌握了 React 的基礎知識,再回過頭來一定會豁然開朗!

如果你喜歡這個關於畫師的夢,我把《坐標 React 星:React 核心思維模型》這本書推薦給你。在書里,我用相同的手法以故事的形式講解 React 的基礎知識,讓你在娛樂中學習。對了,畫師在書里有出場哦!


噹噹423福利來啦!

W29TAJ (20元優惠碼)

噹噹每滿100-50 再疊加20元優惠碼

實付100可用 花80元買原價200元的書

包郵送書

阿浪聯合 博文視點為大家抽取5本《坐標react星》,祝大家好運!

關注【前端有道】公眾號後,在後台回復react獲取抽獎二維碼,掃描即可參與!


為了方便抽獎/兌獎,可以先添加阿浪微信哦

本次活動的開獎日期為:2022-4-24 12:00,中獎者請在24小時內填寫收件地址,否則中獎無效,祝你好運

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()