" />

国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

React渲染機制及相關優(yōu)化方案

瀏覽:6日期:2022-06-12 17:20:55
目錄一、react渲染步驟二、concurrent機制以及產生作用的機會1. 優(yōu)先級調度:2. 遞增式渲染:三、簡單模擬實現(xiàn) concurrent mode 的遞增式渲染四、與優(yōu)先級調度有關的兩個hooks1. useTransition2. useDeferredValue3. useTransition 與 useDeferredValue 的區(qū)別4. 應用場景五、一個小例子1. 下面使用 useTransition 進行優(yōu)化2. 使用 useDeferredValue 進行優(yōu)化補充:為什么VUE不需要設計 Concurrent Mode一、react渲染步驟

準備階段(Prepare Phase)在準備階段,React 會收集組件的依賴關系,建立組件樹的數(shù)據(jù)結構,確定組件的更新優(yōu)先級,并生成用于渲染的工作單元。

計算階段(Compute Phase)在計算階段,React 會根據(jù)組件的更新優(yōu)先級和調度策略,將工作單元分成多個批次進行處理。每個批次都會執(zhí)行一小部分工作單元,以保證用戶界面的響應性。

渲染階段(Render Phase)在渲染階段,React 會根據(jù)工作單元的類型和優(yōu)先級,執(zhí)行相應的渲染操作。這包括創(chuàng)建新的虛擬 DOM 節(jié)點、更新現(xiàn)有的虛擬 DOM 節(jié)點,以及卸載不再需要的組件。

提交階段(Commit Phase)在提交階段,React 會將更新后的虛擬 DOM 節(jié)點映射到實際的 DOM,更新用戶界面。這個階段還會執(zhí)行一些副作用操作,如執(zhí)行useEffect。

二、concurrent機制以及產生作用的機會

注:React 的并發(fā)模式(Concurrency Mode)是一種用于處理大型和復雜應用程序的特性,旨在提高應用程序的性能和響應能力。解決react中狀態(tài)更新就會觸發(fā)該組件及該組件下所有子組件無腦更新而引發(fā)的性能問題;同時提供部分控制作業(yè)調度優(yōu)先級的能力給開發(fā)者使用

在傳統(tǒng)的 React 渲染模式中,更新操作是同步進行的,即在進行更新時,會立即進行組件的重新渲染,可能會阻塞主線程,導致頁面響應變慢或失去響應出現(xiàn)掉幀問題。

而concurrent mode通過引入一種新的調度算法和優(yōu)先級機制,將更新操作劃分為多個優(yōu)先級,使得 React 可以更好地管理和分配任務,以實現(xiàn)更平滑的用戶體驗。

concurrent mode主要具備以下幾個特性:異步渲染、優(yōu)先級調度、遞增式渲染

補充:concurrent mode 主要工作在渲染流程的 Compute Phase 及 Render Phase,因為它們是純粹的 JS 計算意味著可以被拆分,而 commit 階段由于帶有 DOM 更新,不可能 DOM 變更到一半中斷,因此必須一次性執(zhí)行完成

1. 優(yōu)先級調度:

concurrent mode 通過對任務進行優(yōu)先級劃分,React 可以根據(jù)優(yōu)先級動態(tài)地分配和重新分配任務。基于此React 可以更好地響應用戶交互和其他高優(yōu)先級的任務,同時提供了 “useDeferredValue” 、“useTransition” 兩個hooks用于調度作業(yè)任務的優(yōu)先級。

2. 遞增式渲染:

1)concurrent mode 下的渲染是逐步進行的,React 將大量需要重新渲染的組件的工作基于時間片的理念劃分為多個小片段工作,在瀏覽器的每一幀的空閑時間中去執(zhí)行這些渲染工作,而不是一下子全部直接執(zhí)行,這樣有效的避免了掉幀情況的出現(xiàn)。

2)這里也就說明了為什么React官方說 componentWillMount 可能被調用多次的原因,正是因為低優(yōu)先級任務的 render 階段可能被重復的中斷和重新執(zhí)行,而 componentWillMount 就包含在 render 階段中。

注意:工作拆分的最小單元應該是一個fiber節(jié)點,當某個fiber節(jié)點本身的計算就十分巨大時依然會導致卡幀,不過我們可以通過調整工作的優(yōu)先級使得用戶的體驗是平滑的

三、簡單模擬實現(xiàn) concurrent mode 的遞增式渲染下面使用 requestIdleCallback 函數(shù)模擬時間片,在每一幀的空閑時間進行js計算從而達到遞增式渲染的效果

index.html

<!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>Document</title> <script src='https://www.jb51.net/javascript/index.js'></script></head><body> <div id='root'></div> <script>// 調用render提供掛載容器 'root'render(document.getElementById('root')) </script></body></html>

index.js

// 頁面需要渲染的組件function Counter() { return {type: 'span',value: 'hello world',next: { type: 'p', value: 'hello LiHua'} }}const CounterElementDescriptors = { type: 'Function', fn: Counter}// 記錄當前工作let presentWork = null// 記錄根元素let rootElementDescriptor = null // 記錄掛載容器 let elementsContainer = null // 處理單元任務function performUnitOfWork(deadline) { // 判斷當前是否還有待執(zhí)行任務 if (presentWork == null) return commitRoot(rootElementDescriptor) // 當前幀超時,調用 requestIdleCallback 把任務推到下一幀空閑時間執(zhí)行 if (deadline.didTimeout) return requestIdleCallback(executeWorkLoop) // 若是組件則處理依賴關系、若是元素則生成真實dom if (presentWork.type === 'Function') {rootElementDescriptor = presentWorkconst firstChildren = presentWork.fn()firstChildren.parent = presentWorkpresentWork.children = firstChildrenpresentWork = firstChildrenperformUnitOfWork(deadline) } else {const dom = document.createElement(presentWork.type)dom.innerHTML = presentWork.valuepresentWork.dom = dompresentWork = presentWork.nextperformUnitOfWork(deadline) }}// 控制循環(huán)執(zhí)行工作function executeWorkLoop(deadline) { performUnitOfWork(deadline)}// 提供render函數(shù),用于獲取掛載容器和開始渲染計算工作function render(element) { elementsContainer = element presentWork = CounterElementDescriptors requestIdleCallback(executeWorkLoop)}// 模擬commit階段function commitRoot(rootElement) { let renderCHildrenElements = rootElement.children do {elementsContainer.appendChild(renderCHildrenElements.dom)renderCHildrenElements = renderCHildrenElements.next }while(renderCHildrenElements)}四、與優(yōu)先級調度有關的兩個hooks1. useTransition

官方解釋:useTransition 是一個讓你在不阻塞 UI 的情況下來更新狀態(tài)的 React Hook。

通過 useTransition 我們可以將一部分的狀態(tài)更新工作劃分為低優(yōu)先級的異步任務,使它不阻塞主要任務的執(zhí)行同時我們可以依據(jù) useTransition 返回的標志狀態(tài)在渲染期間優(yōu)雅地展示加載狀態(tài),從而提高用戶界面的交互體驗和流暢性useTransition 主要語法如下:import { useTransition } from 'react';function TabContainer() { // isPending 標志,告訴你是否存在待處理的低優(yōu)先級工作。 // startTransition 函數(shù) 允許你將該部分的狀態(tài)更新標記為低優(yōu)先級。 const [isPending, startTransition] = useTransition(); function handle() {startTransition(() => { // 低優(yōu)先級的狀態(tài)更新工作 {......}}); } return ({......} )}2. useDeferredValue

官方解釋:useDeferredValue 是一個 React Hook,可以讓你延遲更新 UI 的某些部分。

通過 useDeferredValue 我們可以將一部分的UI更新工作劃分為低優(yōu)先級的任務,使它不阻塞主要任務的執(zhí)行useTransition 主要語法如下:import { useDeferredValue, useState, } from 'react';function TabContainer() { const [query, setQuery] = useState(''); // 定義的 deferredQuery 獲取的是query的延遲版本 const deferredQuery = useDeferredValue(query); function handle(data) {setQuery(data) } return ( <> <List listData={deferredQuery} /> { ......} </> )}3. useTransition 與 useDeferredValue 的區(qū)別useTransition 用于控制過渡狀態(tài),可以在過渡狀態(tài)中執(zhí)行任務,并提供過渡狀態(tài)的布爾值來判斷是否處于過渡狀態(tài)。useDeferredValue 用于延遲某個值的更新,以避免在渲染過程中處理昂貴的計算或數(shù)據(jù)獲取,確保界面的流暢性。雖然它們都與并發(fā)模式相關,但用途和作用略有不同,具體使用哪一個需要看具體場景。4. 應用場景

1)長列表渲染:當渲染大量列表項時,可以對列表項的渲染任務調節(jié)為低優(yōu)先級異步任務,以保證用戶界面的響應性能。

2)大型表單處理:對于包含大量輸入字段的表單,可以使用合理使用對于hooks將表單提交和驗證等任務進行優(yōu)化調節(jié),以避免阻塞用戶界面。

3)圖片懶加載:當頁面中包含大量圖片時,可以使用 useTransition 將圖片的加載劃分為多個低優(yōu)先級異步任務,在渲染期間逐步加載圖片,以減少對用戶界面的阻塞。

4)異步數(shù)據(jù)加載:當頁面中的數(shù)據(jù)需要從后端異步加載時,可以使用 useTransition 將數(shù)據(jù)的加載劃分為多個異步任務,以保證用戶界面的響應性能。

五、一個小例子以下以長列表渲染為例子做演示

基礎代碼,未作優(yōu)化處理:

import React, { useCallback, useState } from 'react'const index: React.FC = () => { const [list, setList] = useState<any[]>([]) const handleSearch = useCallback((value: string) => { const newList = [] for (let i = 0; i < 5000; i++) {newList.push(value + '-' + i) } setList(newList) }, []) return (<> <input onChange={(e) => handleSearch(e.target.value)} type='text' /> <div>{list.map(item => <div key={item}>數(shù)據(jù)項:{item}</div>)} </div></> )}export default index

當我們進行持續(xù)的輸入時是十分的卡頓的,效果如下:

1. 下面使用 useTransition 進行優(yōu)化降低 “setList(newList)” 的優(yōu)先級,使其不阻塞用戶輸入事件的觸發(fā)

代碼修改如下:

import React, { useCallback, useState, useTransition } from 'react'const index: React.FC = () => { const [list, setList] = useState<any[]>([]) const [isPending, startTransition] = useTransition() const handleSearch = useCallback((value: string) => {startTransition(() => { const newList = [] for (let i = 0; i < 5000; i++) {newList.push(value + '-' + i) } setList(newList)}) }, []) return (<> <input onChange={(e) => handleSearch(e.target.value)} type='text' /> <div>{isPending? '加載中。。。' : list.map(item => <div key={item}>數(shù)據(jù)項:{item}</div>)} </div></> )}export default index

優(yōu)化后效果如下:

2. 使用 useDeferredValue 進行優(yōu)化降低 “列表部分UI” 更新渲染的優(yōu)先級,使其不阻塞用戶輸入事件的觸發(fā)

代碼修改如下:

import React, { memo, useDeferredValue, useState } from 'react'const Item = ({ text }: any) => { return (<div> 數(shù)據(jù)項:{text}</div> )}const List = memo(({ inputValue }: { inputValue: string }) => { let items = []; for (let i = 0; i < 5000; i++) {items.push(<Item key={i} text={inputValue + '-' + i} />); } return (<> {items}</> );})const index: React.FC = () => { const [inputValue, setInputValue] = useState('') const deferredInputValue = useDeferredValue(inputValue) return (<> <input value={inputValue} onChange={(e) => setInputValue(e.target.value)} type='text' /> <List inputValue={deferredInputValue} /></> )}export default index

優(yōu)化后效果如下:

補充:為什么VUE不需要設計 Concurrent Mode出于vue響應式系統(tǒng)的設計實現(xiàn)思路的不同,也就體現(xiàn)了為什么。

1)在vue中,響應式系統(tǒng)通過 proxy 實現(xiàn)對 render函數(shù) 的依賴收集和觸發(fā)更新,基于追蹤組件依賴的響應式數(shù)據(jù)的變化,可以更為精準的實現(xiàn)組件的更新,大大避免了不必要的渲染和更新操作,規(guī)避了react中狀態(tài)更新就會觸發(fā)組件及該組件下所有子組件無腦更新的問題。

2)同時vue的異步更新策略也有助于提高性能和響應能力。Vue會在下一個事件循環(huán)周期中批量更新組件,這樣可以避免頻繁的DOM操作和重復渲染,提高渲染效率。

3)但vue中暫時沒有 useTransition 和 useDeferredValue 類似的功能操作,無法調度控制作業(yè)的優(yōu)先級

以上就是React渲染機制及相關優(yōu)化方案的詳細內容,更多關于React渲染機制的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: JavaScript
主站蜘蛛池模板: 国产不卡在线观看视频 | 国产高清美女一级a毛片久久w | 亚洲一级特黄特黄的大片 | 99久久99视频 | 日韩一区二区三区在线视频 | 日本在线观看网址 | 亚洲国产成人久久综合区 | 欧美在线黄色 | 免费看岛国视频在线观看 | 国产成人免费a在线资源 | 国产精品大全国产精品 | 欧美一区三区 | 国产在线观看一区二区三区四区 | 国产免费网 | 日本一道免费一区二区三区 | 免费在线观看毛片 | 久久亚洲国产欧洲精品一 | 欧美中文字幕一区二区三区 | 美女在线网站免费的 | 成人a大片高清在线观看 | 成人精品视频一区二区三区 | 这里只有久久精品视频 | 九九久久久久久久爱 | 亚洲日本在线看片 | 亚洲成在 | 欧美a欧美 | 色午夜在线 | 在线看毛片网站 | 一a一片一级一片啪啪 | 欧美日韩视频二区三区 | 亚洲成人免费观看 | 久久视精品 | 91热视频在线观看 | 最近手机中文字幕1 | 亚洲天堂最新网址 | 国产亚洲福利精品一区二区 | 亚洲精品久久玖玖玖玖 | 一级做a爰片久久毛片潮喷 一级做a爰片久久毛片美女 | 毛片网站视频 | 亚洲日韩中文字幕天堂不卡 | 欧美日韩综合网在线观看 |