中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React17啟發式更新算法是什么

發布時間:2022-02-25 10:01:46 來源:億速云 閱讀:115 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“React17啟發式更新算法是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“React17啟發式更新算法是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

為什么會出現啟發式更新算法

框架的運行性能是框架設計者在設計框架時需要重點關注的點。

Vue使用模版語法,可以在編譯時對確定的模版作出優化。

ReactJS寫法太過靈活,使他在編譯時優化方面先天不足。

所以,React的優化主要在運行時。

React15的痛點

在運行時優化方面,React一直在努力。

比如,React15實現了batchedUpdates(批量更新)。

即同一事件回調函數上下文中的多次setState只會觸發一次更新。

但是,如果單次更新就很耗時,頁面還是會卡頓(這在一個維護時間很長的大應用中是很常見的)。

這是因為React15的更新流程是同步執行的,一旦開始更新直到頁面渲染前都不能中斷。

為了解決同步更新長時間占用線程導致頁面卡頓的問題,也為了探索運行時優化的更多可能,React開始重構并一直持續至今。

重構的目標是實現Concurrent Mode(并發模式)。

(推薦教程:React教程)

Concurrent Mode

Concurrent Mode的目的是實現一套可中斷/恢復的更新機制。

其由兩部分組成:

  • 一套協程架構

  • 基于協程架構的啟發式更新算法

其中,協程架構就是React16中實現的Fiber Reconciler

我們可以將Fiber Reconciler理解為React自己實現的Generator

Fiber Reconciler從理念到源碼的詳細介紹見這里

協程架構使更新可以在需要的時機被中斷,這樣瀏覽器就有時間完成樣式布局與樣式繪制,減少卡頓(掉幀)的出現。

當瀏覽器進入下一次事件循環,協程架構可以恢復中斷或者拋棄之前的更新,重新開始新的更新流程。

啟發式更新算法就是控制協程架構工作方式的算法。

React16的啟發式更新算法

啟發式更新算法的啟發式指什么呢?

啟發式指不通過顯式的指派,而是通過優先級調度更新。

其中優先級來源于人機交互的研究成果。

比如:

人機交互的研究成果表明:

  • 當用戶在輸入框輸入內容時,希望輸入的內容能實時響應在輸入框

  • 當異步請求數據后,即使等待一會兒再顯示內容,用戶也是可以接受的

基于此,在React16中

輸入框輸入內容觸發的更新優先級 > 請求數據返回后觸發更新優先級

算法實現 在React16、17中,在組件內執行this.setState后會在該組件對應的fiber節點內產生一種鏈表數據結構update

其中,update.expirationTimes為類似時間戳的字段,表示優先級。

expirationTimes從字面意義理解為過期時間。

該值離當前時間越接近,該update 優先級越高。

update.expirationTimes超過當前時間,則代表該update過期,優先級變為最高(即同步)。

一棵fiber樹的多個fiber節點可能存在多個update

每次Fiber Reconciler調度更新時,會在所有fiber節點的所有update.expirationTimes中選擇一個expirationTimes(一般選擇最大的),作為本次更新的優先級。

并從根fiber節點開始向下構建新的fiber樹。

構建過程中如果某個fiber節點包含update,且

update.expirationTimes >= expirationTimes

則該update對應的state變化會體現在本次更新中。

可以理解為:每次更新,都會選定一個優先級(expirationTimes),最終頁面會渲染為該優先級對應update的快照。

算法缺陷

如果只考慮中斷/繼續這樣的 CPU 操作,以expirationTimes大小作為衡量優先級依據的模型可以很好工作。

但是expirationTimes模型不能滿足 IO 操作(Suspense)。

在該模型下,高優先級 IO 任務(Suspense)會中斷低優先級 CPU 任務。

還記得么,每次更新,都是以某一優先級作為整棵樹的優先級更新標準,而不僅僅是某一組件,即使更新的源頭(update)確實是某個組件產生的。

expirationTimes模型只能區分是否>=expirationTimes這種情況。

為了拓展Concurrent Mode能力邊界,需要一種更細粒度的啟發式優先級更新算法。

(推薦教程:React入門實例教程)

React17啟發式更新算法

最理想的模型是:可以指定任意幾個優先級,更新會以這些優先級對應update生成頁面快照。

但是現有架構下,該方案實現上有瓶頸。

妥協之下,React17的解決方案是:指定一個連續的優先級區間,每次更新都會以區間內包含的優先級生成對應頁面快照。

這種優先級區間模型被稱為lanes(車道模型)。

具體做法是:使用一個31位的二進制代表31種可能性。

  • 其中每個bit被稱為一個lane(車道),代表優先級

  • 某幾個lane組成的二進制數被稱為一個lanes,代表一批優先級

可以從源碼中看到,從藍線一路劃下去,每個bit都對應一個lanelanes

update產生,會根據React16同樣的啟發式方式,獲得如下優先級的一種:

export const SyncLanePriority: LanePriority = 17; export const SyncBatchedLanePriority: LanePriority = 16; export const InputDiscreteLanePriority: LanePriority = 14; export const InputContinuousLanePriority: LanePriority = 12; export const DefaultLanePriority: LanePriority = 10; export const TransitionShortLanePriority: LanePriority = 8; export const TransitionLongLanePriority: LanePriority = 6;

其中值越高,優先級越大。

比如:

  • 點擊事件回調中觸發this.setState產生的update會獲得InputDiscreteLanePriority

  • 同步的update會獲得SyncLanePriority

接下來,update會以priority為線索尋找沒被占用的lane

如果當前fiber樹已經存在更新且更新的lanes包含了該lane,則update需要尋找其他lane

比如,InputDiscreteLanePriority對應的lanesInputDiscreteLanes

// 第4、5位為1 const InputDiscreteLanes: Lanes = 0b0000000000000000000000000011000;

lanes包含第4、5位 2 個 bit位。

如果其中

// 第五位為1 0b0000000000000000000000000010000

第五位的lane已經被占用,則該update可以嘗試占有后一個,即

// 第四位為1 0b0000000000000000000000000001000

如果InputDiscreteLanes的兩個lane都被占用,則該update的優先級會下降到InputContinuousLanePriority并繼續尋找空余的lane

這個過程就像:購物中心每一層(不同優先級)都有一個露天停車場(lanes),停車場有多個車位(lane)。

我們先開車到頂樓找車位(lane),如果沒有車位就下一樓繼續找。

直到找到空余車位。

由于lanes可以包含多個lane,可以很方便的區分 IO 操作(Suspense)與 CPU 操作。

當構建fiber樹進入構建Suspense子樹時,會將Suspenselane插入本次更新選定的lanes中。

當構建離開Suspense子樹時,會將Suspense lane從本次更新的lanes中移除。

讀到這里,這篇“React17啟發式更新算法是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武隆县| 华阴市| 兴山县| 德惠市| 弥渡县| 姚安县| 潮州市| 辉县市| 北票市| 聂荣县| 桑植县| 专栏| 边坝县| 嵊州市| 富民县| 阿城市| 天门市| 洱源县| 棋牌| 延吉市| 宜良县| 冀州市| 潜江市| 双牌县| 卢湾区| 晋中市| 新昌县| 阳山县| 北票市| 南投市| 泰来县| 额尔古纳市| 肇源县| 治多县| 浠水县| 东山县| 图木舒克市| 寻甸| 四会市| 宜丰县| 景谷|