久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      react中什么是fiber

      Fiber是React新的調(diào)度算法,是對核心算法的一次重新實現(xiàn)。React Fiber把更新過程碎片化,每執(zhí)行完一段更新過程,就把控制權(quán)交還給React負(fù)責(zé)任務(wù)協(xié)調(diào)的模塊,看看有沒有其他緊急任務(wù)要做,如果有緊急任務(wù),就去做緊急任務(wù)。

      react中什么是fiber

      本教程操作環(huán)境:Windows7系統(tǒng)、react17.0.1版、Dell G3電腦。

      react16 版本之后引入了 fiber,整個架構(gòu)層面的 調(diào)度、協(xié)調(diào)、diff 算法以及渲染等都與 fiber 密切相關(guān)。

      React Fiber是個什么東西呢?

      react在進(jìn)行組件渲染時,從setState開始到渲染完成整個過程是同步的(“一氣呵成”)。如果需要渲染的組件比較龐大,js執(zhí)行會占據(jù)主線程時間較長,會導(dǎo)致頁面響應(yīng)度變差,使得react在動畫、手勢等應(yīng)用中效果比較差。

      為了解決這個問題,react團(tuán)隊經(jīng)過兩年的工作,重寫了react中核心算法——reconciliation。并在v16版本中發(fā)布了這個新的特性。為了區(qū)別之前和之后的reconciler,通常將之前的reconciler稱為stack reconciler,重寫后的稱為fiber reconciler,簡稱為Fiber。

      官方的一句話解釋是“React Fiber是對核心算法的一次重新實現(xiàn)”。

      Fiber 可以提升復(fù)雜React 應(yīng)用的可響應(yīng)性和性能。Fiber 即是React新的調(diào)度算法(reconciliation algorithm)

      React Fiber 把更新過程碎片化,每執(zhí)行完一段更新過程,就把控制權(quán)交還給 React 負(fù)責(zé)任務(wù)協(xié)調(diào)的模塊,看看有沒有其他緊急任務(wù)要做,如果沒有就繼續(xù)去更新,如果有緊急任務(wù),那就去做緊急任務(wù)。

      react在進(jìn)行組件渲染時,從setState開始到渲染完成整個過程是同步的(“一氣呵成”)。如果需要渲染的組件比較龐大,js執(zhí)行會占據(jù)主線程時間較長,會導(dǎo)致頁面響應(yīng)度變差,使得react在動畫、手勢等應(yīng)用中效果比較差。

      為了解決這個問題,react團(tuán)隊經(jīng)過兩年的工作,重寫了react中核心算法——reconciliation。并在v16版本中發(fā)布了這個新的特性。為了區(qū)別之前和之后的reconciler,通常將之前的reconciler稱為stack reconciler,重寫后的稱為fiber reconciler,簡稱為Fiber。

      react中什么是fiber

      react中什么是fiber

      卡頓原因

      Stack reconciler的工作流程很像函數(shù)的調(diào)用過程。父組件里調(diào)子組件,可以類比為函數(shù)的遞歸(這也是為什么被稱為stack reconciler的原因)。在setState后,react會立即開始reconciliation過程,從父節(jié)點(diǎn)(Virtual DOM)開始遍歷,以找出不同。將所有的Virtual DOM遍歷完成后,reconciler才能給出當(dāng)前需要修改真實DOM的信息,并傳遞給renderer,進(jìn)行渲染,然后屏幕上才會顯示此次更新內(nèi)容。對于特別龐大的vDOM樹來說,reconciliation過程會很長(x00ms),在這期間,主線程是被js占用的,因此任何交互、布局、渲染都會停止,給用戶的感覺就是頁面被卡住了。

      react中什么是fiber

      Scheduler

      scheduling(調(diào)度)是fiber reconciliation的一個過程,主要決定應(yīng)該在何時做什么。?的過程表明在stack reconciler中,reconciliation是“一氣呵成”,對于函數(shù)來說,這沒什么問題,因為我們只想要函數(shù)的運(yùn)行結(jié)果,但對于UI來說還需要考慮以下問題:

      • 并不是所有的state更新都需要立即顯示出來,比如屏幕之外的部分的更新
      • 并不是所有的更新優(yōu)先級都是一樣的,比如用戶輸入的響應(yīng)優(yōu)先級要比通過請求填充內(nèi)容的響應(yīng)優(yōu)先級更高
      • 理想情況下,對于某些高優(yōu)先級的操作,應(yīng)該是可以打斷低優(yōu)先級的操作執(zhí)行的,比如用戶輸入時,頁面的某個評論還在reconciliation,應(yīng)該優(yōu)先響應(yīng)用戶輸入

      所以理想狀況下reconciliation的過程應(yīng)該是像下圖所示一樣,每次只做一個很小的任務(wù),做完后能夠“喘口氣兒”,回到主線程看下有沒有什么更高優(yōu)先級的任務(wù)需要處理,如果又則先處理更高優(yōu)先級的任務(wù),沒有則繼續(xù)執(zhí)行(cooperative scheduling 合作式調(diào)度)。

      react中什么是fiber

      任務(wù)拆分 fiber-tree & fiber

      先看一下stack-reconciler下的react是怎么工作的。代碼中創(chuàng)建(或更新)一些元素,react會根據(jù)這些元素創(chuàng)建(或更新)Virtual DOM,然后react根據(jù)更新前后virtual DOM的區(qū)別,去修改真正的DOM。注意,在stack reconciler下,DOM的更新是同步的,也就是說,在virtual DOM的比對過程中,發(fā)現(xiàn)一個instance有更新,會立即執(zhí)行DOM操作。

      react中什么是fiber

      而fiber-conciler下,操作是可以分成很多小部分,并且可以被中斷的,所以同步操作DOM可能會導(dǎo)致fiber-tree與實際DOM的不同步。對于每個節(jié)點(diǎn)來說,其不光存儲了對應(yīng)元素的基本信息,還要保存一些用于任務(wù)調(diào)度的信息。因此,fiber僅僅是一個對象,表征reconciliation階段所能拆分的最小工作單元,和上圖中的react instance一一對應(yīng)。通過stateNode屬性管理Instance自身的特性。通過child和sibling表征當(dāng)前工作單元的下一個工作單元,return表示處理完成后返回結(jié)果所要合并的目標(biāo),通常指向父節(jié)點(diǎn)。整個結(jié)構(gòu)是一個鏈表樹。每個工作單元(fiber)執(zhí)行完成后,都會查看是否還繼續(xù)擁有主線程時間片,如果有繼續(xù)下一個,如果沒有則先處理其他高優(yōu)先級事務(wù),等主線程空閑下來繼續(xù)執(zhí)行。

      react中什么是fiber

      fiber {  	stateNode: {},    child: {},    return: {},    sibling: {}, }復(fù)制代碼

      舉個例子

      當(dāng)前頁面包含一個列表,通過該列表渲染出一個button和一組Item,Item中包含一個div,其中的內(nèi)容為數(shù)字。通過點(diǎn)擊button,可以使列表中的所有數(shù)字進(jìn)行平方。另外有一個按鈕,點(diǎn)擊可以調(diào)節(jié)字體大小。

      react中什么是fiber

      頁面渲染完成后,就會初始化生成一個fiber-tree。初始化fiber-tree和初始化Virtual DOM tree沒什么區(qū)別,這里就不再贅述。

      react中什么是fiber

      于此同時,react還會維護(hù)一個workInProgressTree。workInProgressTree用于計算更新,完成reconciliation過程。

      react中什么是fiber

      用戶點(diǎn)擊平方按鈕后,利用各個元素平方后的list調(diào)用setState,react會把當(dāng)前的更新送入list組件對應(yīng)的update queue中。但是react并不會立即執(zhí)行對比并修改DOM的操作。而是交給scheduler去處理。

      react中什么是fiber

      scheduler會根據(jù)當(dāng)前主線程的使用情況去處理這次update。為了實現(xiàn)這種特性,使用了requestIdelCallbackAPI。對于不支持這個API的瀏覽器,react會加上pollyfill。

      總的來講,通常,客戶端線程執(zhí)行任務(wù)時會以幀的形式劃分,大部分設(shè)備控制在30-60幀是不會影響用戶體驗;在兩個執(zhí)行幀之間,主線程通常會有一小段空閑時間,requestIdleCallback可以在這個空閑期(Idle Period)調(diào)用空閑期回調(diào)(Idle Callback),執(zhí)行一些任務(wù)

      react中什么是fiber

      • 低優(yōu)先級任務(wù)由requestIdleCallback處理;

      • 高優(yōu)先級任務(wù),如動畫相關(guān)的由requestAnimationFrame處理;

      • requestIdleCallback可以在多個空閑期調(diào)用空閑期回調(diào),執(zhí)行任務(wù);

      • requestIdleCallback方法提供deadline,即任務(wù)執(zhí)行限制時間,以切分任務(wù),避免長時間執(zhí)行,阻塞UI渲染而導(dǎo)致掉幀;

      一旦reconciliation過程得到時間片,就開始進(jìn)入work loop。work loop機(jī)制可以讓react在計算狀態(tài)和等待狀態(tài)之間進(jìn)行切換。為了達(dá)到這個目的,對于每個loop而言,需要追蹤兩個東西:下一個工作單元(下一個待處理的fiber);當(dāng)前還能占用主線程的時間。第一個loop,下一個待處理單元為根節(jié)點(diǎn)。

      react中什么是fiber

      因為根節(jié)點(diǎn)上的更新隊列為空,所以直接從fiber-tree上將根節(jié)點(diǎn)復(fù)制到workInProgressTree中去。根節(jié)點(diǎn)中包含指向子節(jié)點(diǎn)(List)的指針。

      react中什么是fiber

      根節(jié)點(diǎn)沒有什么更新操作,根據(jù)其child指針,接下來把List節(jié)點(diǎn)及其對應(yīng)的update queue也復(fù)制到workinprogress中。List插入后,向其父節(jié)點(diǎn)返回,標(biāo)志根節(jié)點(diǎn)的處理完成。

      react中什么是fiber

      根節(jié)點(diǎn)處理完成后,react此時檢查時間片是否用完。如果沒有用完,根據(jù)其保存的下個工作單元的信息開始處理下一個節(jié)點(diǎn)List。

      react中什么是fiber

      接下來進(jìn)入處理List的work loop,List中包含更新,因此此時react會調(diào)用setState時傳入的updater funciton獲取最新的state值,此時應(yīng)該是[1,4,9]。通常我們現(xiàn)在在調(diào)用setState傳入的是一個對象,但在使用fiber conciler時,必須傳入一個函數(shù),函數(shù)的返回值是要更新的state。react從很早的版本就開始支持這種寫法了,不過通常沒有人用。在之后的react版本中,可能會廢棄直接傳入對象的寫法。

      setState({}, callback); // stack concilersetState(() => { return {} }, callback); // fiber conciler復(fù)制代碼

      在獲取到最新的state值后,react會更新List的state和props值,然后調(diào)用render,然后得到一組通過更新后的list值生成的elements。react會根據(jù)生成elements的類型,來決定fiber是否可重用。對于當(dāng)前情況來說,新生成的elments類型并沒有變(依然是Button和Item),所以react會直接從fiber-tree中復(fù)制這些elements對應(yīng)的fiber到workInProgress 中。并給List打上標(biāo)簽,因為這是一個需要更新的節(jié)點(diǎn)。

      react中什么是fiber

      List節(jié)點(diǎn)處理完成,react仍然會檢查當(dāng)前時間片是否夠用。如果夠用則處理下一個,也就是button。加入這個時候,用戶點(diǎn)擊了放大字體的按鈕。這個放大字體的操作,純粹由js實現(xiàn),跟react無關(guān)。但是操作并不能立即生效,因為react的時間片還未用完,因此接下來仍然要繼續(xù)處理button。

      react中什么是fiber

      button沒有任何子節(jié)點(diǎn),所以此時可以返回,并標(biāo)志button處理完成。如果button有改變,需要打上tag,但是當(dāng)前情況沒有,只需要標(biāo)記完成即可。

      react中什么是fiber

      老規(guī)矩,處理完一個節(jié)點(diǎn)先看時間夠不夠用。注意這里放大字體的操作已經(jīng)在等候釋放主線程了。

      react中什么是fiber

      接下來處理第一個item。通過shouldComponentUpdate鉤子可以根據(jù)傳入的props判斷其是否需要改變。對于第一個Item而言,更改前后都是1,所以不會改變,shouldComponentUpdate返回false,復(fù)制div,處理完成,檢查時間,如果還有時間進(jìn)入第二個Item。

      第二個Item shouldComponentUpdate返回true,所以需要打上tag,標(biāo)志需要更新,復(fù)制div,調(diào)用render,講div中的內(nèi)容從2更新為4,因為div有更新,所以標(biāo)記div。當(dāng)前節(jié)點(diǎn)處理完成。

      react中什么是fiber

      對于上面這種情況,div已經(jīng)是葉子節(jié)點(diǎn),且沒有任何兄弟節(jié)點(diǎn),且其值已經(jīng)更新,這時候,需要將此節(jié)點(diǎn)改變產(chǎn)生的effect合并到父節(jié)點(diǎn)中。此時react會維護(hù)一個列表,其中記錄所有產(chǎn)生effect的元素。

      react中什么是fiber

      合并后,回到父節(jié)點(diǎn)Item,父節(jié)點(diǎn)標(biāo)記完成。

      react中什么是fiber

      下一個工作單元是Item,在進(jìn)入Item之前,檢查時間。但這個時候時間用完了。此時react必須交換主線程,并告訴主線程以后要為其分配時間以完成剩下的操作。

      react中什么是fiber

      主線程接下來進(jìn)行放大字體的操作。完成后執(zhí)行react接下來的操作,跟上一個Item的處理流程幾乎一樣,處理完成后整個fiber-tree和workInProgress如下:

      react中什么是fiber

      完成后,Item向List返回并merge effect,effect List現(xiàn)在如下所示:

      react中什么是fiber

      此時List向根節(jié)點(diǎn)返回并merge effect,所有節(jié)點(diǎn)都可以標(biāo)記完成了。此時react將workInProgress標(biāo)記為pendingCommit。意思是可以進(jìn)入commit階段了。

      react中什么是fiber

      此時,要做的是還是檢查時間夠不夠用,如果沒有時間,會等到時間再去提交修改到DOM。進(jìn)入到階段2后,reacDOM會根據(jù)階段1計算出來的effect-list來更新DOM。

      更新完DOM之后,workInProgress就完全和DOM保持一致了,為了讓當(dāng)前的fiber-tree和DOM保持一直,react交換了current和workinProgress兩個指針。

      react中什么是fiber

      事實上,react大部分時間都在維持兩個樹(Double-buffering)。這可以縮減下次更新時,分配內(nèi)存、垃圾清理的時間。commit完成后,執(zhí)行componentDidMount函數(shù)。

      小結(jié)

      通過將reconciliation過程,分解成小的工作單元的方式,可以讓頁面對于瀏覽器事件的響應(yīng)更加及時。但是另外一個問題還是沒有解決,就是如果當(dāng)前在處理的react渲染耗時較長,仍然會阻塞后面的react渲染。這就是為什么fiber reconciler增加了優(yōu)先級策略。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號