" />

日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

React渲染機制及相關優化方案

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

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

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

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

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

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

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

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

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

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

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

1. 優先級調度:

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

2. 遞增式渲染:

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

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

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

三、簡單模擬實現 concurrent mode 的遞增式渲染下面使用 requestIdleCallback 函數模擬時間片,在每一幀的空閑時間進行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) { // 判斷當前是否還有待執行任務 if (presentWork == null) return commitRoot(rootElementDescriptor) // 當前幀超時,調用 requestIdleCallback 把任務推到下一幀空閑時間執行 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) }}// 控制循環執行工作function executeWorkLoop(deadline) { performUnitOfWork(deadline)}// 提供render函數,用于獲取掛載容器和開始渲染計算工作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)}四、與優先級調度有關的兩個hooks1. useTransition

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

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

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

通過 useDeferredValue 我們可以將一部分的UI更新工作劃分為低優先級的任務,使它不阻塞主要任務的執行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 的區別useTransition 用于控制過渡狀態,可以在過渡狀態中執行任務,并提供過渡狀態的布爾值來判斷是否處于過渡狀態。useDeferredValue 用于延遲某個值的更新,以避免在渲染過程中處理昂貴的計算或數據獲取,確保界面的流暢性。雖然它們都與并發模式相關,但用途和作用略有不同,具體使用哪一個需要看具體場景。4. 應用場景

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

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

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

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

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

基礎代碼,未作優化處理:

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}>數據項:{item}</div>)} </div></> )}export default index

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

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

代碼修改如下:

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}>數據項:{item}</div>)} </div></> )}export default index

優化后效果如下:

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

代碼修改如下:

import React, { memo, useDeferredValue, useState } from 'react'const Item = ({ text }: any) => { return (<div> 數據項:{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

優化后效果如下:

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

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

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

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

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

標簽: JavaScript
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲v天堂v手机在线| 黑丝一区二区三区| 欧美日韩国产传媒| 国产色噜噜噜91在线精品 | 日本成人中文字幕| 国产毛片精品| 亚洲三级网站| 日韩一级网站| 日韩精品久久久久久久软件91| 日韩手机在线| 亚洲另类av| 国产精品三级| 欧美日韩在线网站| 欧美国产不卡| 久久亚洲风情| 欧美天堂一区| 欧美日韩在线二区| 国产精品4hu.www| 日本一二区不卡| 激情欧美丁香| 亚洲有吗中文字幕| 久久亚洲黄色| 老色鬼久久亚洲一区二区| 久久国产精品99国产| 在线日韩视频| 国产精品久久久久久久久久10秀| 99在线精品免费视频九九视| 亚洲精品极品| 亚洲精一区二区三区| 久久精品国产大片免费观看| 97欧美在线视频| 欧美国产精品| 中文字幕成在线观看| 国产精品2区| 国产精品天堂蜜av在线播放| 在线亚洲激情| 欧美天堂在线| 久久激情五月激情| 日韩影片在线观看| 国产精品亲子伦av一区二区三区| 1024精品久久久久久久久| 欧美欧美黄在线二区| 亚洲乱码视频| 国产精品女主播一区二区三区 | 色8久久久久| 久久亚洲成人| 99精品国产一区二区三区| 秋霞国产精品| 日韩一区二区久久| 香蕉久久久久久久av网站| 一区二区精品| 国产精品日本一区二区三区在线| 免费在线成人| 久久久久网站| 国产偷自视频区视频一区二区| 欧美午夜不卡| 日韩激情啪啪| 91精品啪在线观看国产爱臀| 久久精品国产福利| 欧美亚洲国产激情| 中文字幕免费一区二区| 久久激情av| 九九精品调教| 红桃视频欧美| 日韩精品福利一区二区三区| 国产乱论精品| 精品72久久久久中文字幕| 久久人人精品| 亚洲精品乱码| 精品少妇av| 亚洲v在线看| 亚洲精品三级| 国产一区二区久久久久| 波多野结衣一区| 亚洲91网站| 成人综合一区| 久久国产66| 久久精品国产精品亚洲毛片| 国精品一区二区三区| 99久久久久| 日韩精品久久理论片| 夜鲁夜鲁夜鲁视频在线播放| 激情久久五月| 国产精品视频3p| 蜜臀91精品国产高清在线观看| 日本中文字幕一区二区视频| 国产高清不卡| 69堂精品视频在线播放| 久久狠狠婷婷| 国产精品调教视频| 免费国产亚洲视频| 日韩电影二区| 国产精品s色| 免费在线观看日韩欧美| 久久视频一区| 国产福利资源一区| 日韩视频中文| 欧美午夜不卡影院在线观看完整版免费| 久久婷婷丁香| 久久国内精品视频| 日韩av免费大片| 久久aⅴ国产紧身牛仔裤| 国产精选久久| 亚洲少妇在线| 亚洲精品一二三区区别| 日本伊人久久| 一区二区亚洲精品| 欧美日韩一区二区综合| 精品国产亚洲一区二区三区大结局| 国产精品美女久久久久久不卡| 美国欧美日韩国产在线播放| 欧美成a人国产精品高清乱码在线观看片在线观看久 | av成人国产| 国产传媒在线| 国产伦乱精品| 亚洲欧洲日韩| 欧美+日本+国产+在线a∨观看| 亚洲精品视频一二三区| 在线观看精品| 国产一区二区三区不卡视频网站| 青草国产精品久久久久久| 五月婷婷亚洲| 午夜精品一区二区三区国产| 中文av在线全新| 国产 日韩 欧美一区| 日本黄色精品| 久久91视频| 国产一二在线播放| 加勒比视频一区| 婷婷六月综合| 国产精品一区二区中文字幕| 日韩中文字幕亚洲一区二区va在线| 麻豆极品一区二区三区| 国产精品videossex| 日本午夜免费一区二区| 蜜桃一区二区三区在线观看| 亚洲男人在线| 亚洲综合色婷婷在线观看| 国产精品美女久久久| 亚洲免费高清| 香蕉成人av| 亚洲高清二区| 欧美特黄一区| 久久99伊人| 亚洲精品乱码| 日本午夜精品一区二区三区电影| 日韩精品免费一区二区夜夜嗨| 蜜臀国产一区二区三区在线播放| 久久香蕉精品| 欧美一区=区三区| 欧美激情网址| 成人片免费看| 国产精品av一区二区| aa亚洲婷婷| 亚洲精品欧美| 久久爱www成人| 日韩欧美看国产| 伊人久久婷婷| 日韩激情av在线| 国产精品久久久久久av公交车| 国产一区二区三区免费在线| 成人羞羞视频在线看网址| 亚洲成人精品| 欧美日韩国产探花| 蜜臀av一区二区在线免费观看 | 亚洲欧美日韩高清在线| 中文不卡在线| 国产精品一页| 欧美一区二区三区高清视频| 亚洲欧洲专区| 91亚洲国产成人久久精品| 亚洲精品a级片| 日本免费新一区视频| 国产精品伦理久久久久久| 日韩午夜高潮| 国产精品宾馆| 亚洲精品在线影院| 蜜桃视频一区二区三区| 乱一区二区av| 日本欧美一区二区| 国产精品13p| 美女精品网站| 国产videos久久| 免费观看日韩电影| 超碰成人av| 亚洲一区二区小说| 狠狠久久伊人中文字幕| 丝袜诱惑制服诱惑色一区在线观看| 美女性感视频久久| 在线亚洲观看| 成人日韩av| 视频在线观看国产精品| 国产精品久久久久蜜臀| 日韩精品一区第一页| sm捆绑调教国产免费网站在线观看| 天使萌一区二区三区免费观看| 精品久久不卡| 日本成人手机在线| 91精品一区国产高清在线gif| 国产欧美在线|