" />

电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:6日期: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
主站蜘蛛池模板: 有机废气处理-rto焚烧炉-催化燃烧设备-VOC冷凝回收装置-三梯环境 | 广州/东莞小字符喷码机-热转印打码机-喷码机厂家-广州瑞润科技 | 精益专家 - 设备管理软件|HSE管理系统|设备管理系统|EHS安全管理系统 | 中空玻璃生产线,玻璃加工设备,全自动封胶线,铝条折弯机,双组份打胶机,丁基胶/卧式/立式全自动涂布机,玻璃设备-山东昌盛数控设备有限公司 | 沈阳网站建设_沈阳网站制作_沈阳网页设计-做网站就找示剑新零售 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | 柴油机_柴油发电机_厂家_品牌-江苏卡得城仕发动机有限公司 | 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 沈阳网站建设_沈阳网站制作_沈阳网页设计-做网站就找示剑新零售 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 安全光栅|射频导纳物位开关|音叉料位计|雷达液位计|两级跑偏开关|双向拉绳开关-山东卓信机械有限公司 | 武汉天安盾电子设备有限公司 - 安盾安检,武汉安检门,武汉安检机,武汉金属探测器,武汉测温安检门,武汉X光行李安检机,武汉防爆罐,武汉车底安全检查,武汉液体探测仪,武汉安检防爆设备 | 药品仓库用除湿机-变电站用防爆空调-油漆房用防爆空调-杭州特奥环保科技有限公司 | 小型数控车床-数控车床厂家-双头数控车床| 武汉刮刮奖_刮刮卡印刷厂_为企业提供门票印刷_武汉合格证印刷_现金劵代金券印刷制作 - 武汉泽雅印刷有限公司 | ICP备案查询_APP备案查询_小程序备案查询 - 备案巴巴 | 屏蔽泵厂家,化工屏蔽泵_维修-淄博泵业 | 雷达液位计_超声波风速风向仪_雨量传感器_辐射传感器-山东风途物联网 | 活性炭厂家-蜂窝活性炭-粉状/柱状/果壳/椰壳活性炭-大千净化-活性炭 | 南溪在线-南溪招聘找工作、找房子、找对象,南溪综合生活信息门户! | 砂磨机_立式纳米砂磨机_实验室砂磨机-广州儒佳化工设备厂家 | 福建成考网-福建成人高考网| 播音主持培训-中影人教育播音主持学苑「官网」-中国艺考界的贵族学校 | 防勒索软件_数据防泄密_Trellix(原McAfee)核心代理商_Trellix(原Fireeye)售后-广州文智信息科技有限公司 | 深圳法律咨询【24小时在线】深圳律师咨询免费| 众能联合-提供高空车_升降机_吊车_挖机等一站工程设备租赁 | 苏州教学设备-化工教学设备-环境工程教学模型|同科教仪 | 百方网-百方电气网,电工电气行业专业的B2B电子商务平台 | 电采暖锅炉_超低温空气源热泵_空气源热水器-鑫鲁禹电锅炉空气能热泵厂家 | 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 | 济宁工业提升门|济宁电动防火门|济宁快速堆积门-济宁市统一电动门有限公司 | 聚丙烯酰胺PAM-聚合氯化铝PAC-絮凝剂-河南博旭环保科技有限公司 巨野电机维修-水泵维修-巨野县飞宇机电维修有限公司 | 强效碱性清洗剂-实验室中性清洗剂-食品级高纯氮气发生器-上海润榕科学器材有限公司 | 云南标线|昆明划线|道路标线|交通标线-就选云南云路施工公司-云南云路科技有限公司 | 数年网路-免费在线工具您的在线工具箱-shuyear.com | 飞象网 - 通信人每天必上的网站| 手机存放柜,超市储物柜,电子储物柜,自动寄存柜,行李寄存柜,自动存包柜,条码存包柜-上海天琪实业有限公司 | 北京浩云律师事务所-企业法律顾问_破产清算等公司法律服务 | 郑州大巴车出租|中巴车租赁|旅游大巴租车|包车|郑州旅游大巴车租赁有限公司 | 液压油缸-液压站生产厂家-洛阳泰诺液压科技有限公司 | 杭州月嫂技术培训服务公司-催乳师培训中心报名费用-产后康复师培训机构-杭州优贝姆健康管理有限公司 | 模具ERP_模具管理系统_模具mes_模具进度管理_东莞市精纬软件有限公司 |