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

溫馨提示×

溫馨提示×

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

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

React原理實例分析

發布時間:2022-07-29 17:27:40 來源:億速云 閱讀:137 作者:iii 欄目:開發技術

本篇內容主要講解“React原理實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“React原理實例分析”吧!

VDOM(虛擬dom)

react和vue都是基于vdom的前端框架。

web界面由DOM樹來構建,當其中一部分發生變化時,其實就是對應的某個節點發生了變化。

若一次操作中有十次更新DOM的動作,虛擬DOM不會立即操作DOM,而是將這十次更新的diff內容保存到本地的一個js對象中,最終將這個js對象一次性attach到DOM樹上,再進行后續的操作。

用js對象模擬DOM節點的好處是:

  • 頁面的更新可以先全部反映在js對象(虛擬DOM)上,精準的對比關心的屬性,避免大量無謂的計算。等更新完成后,再將最終的js對象映射成真是的DOM,交由瀏覽器去繪制。

  • 為應用帶來的跨平臺的能力,不再僅僅局限于瀏覽器端。比如:React-Native、canvas等。

//虛擬dom對象
{
    type: 'div',
    props: {
        id: 'aaa',
        className: ['bbb', 'ccc'],
        onClick: function() {}
    },
    children: []
}

react中,jsx由babel轉義再經過render后生成我們想要的VDOM(虛擬DOM)。

Fiber架構

react15的時候,和 vue 的渲染流程還是很像的,都是遞歸渲染 vdom,增刪改 dom 就行。

但是因為狀態管理的差異導致了架構的差異。react的setState會渲染整個vdom,而一個應用的所有 vdom 可能是很龐大的,計算量就可能很大。

瀏覽器里 js 計算時間太長是會阻塞渲染的,會占用每一幀的動畫、重繪重排的時間,這樣動畫就會卡頓。

那能不能把計算量拆分一下,每一幀計算一部分,不要阻塞動畫的渲染呢?

順著這個思路,react 就改造為了 fiber 架構,目標是打斷計算,分多次進行。

渲染的時候不要直接更新到 dom 了,只找到變化的部分,打個增刪改的標記,創建好 dom,等全部計算完了一次性更新到 dom 就好了。

初始化渲染

根據 React Element 生成對應的 Fiber 樹

1.根據 React Element 生成對應的 Fiber 樹

首次執行ReactDOM.render 會創建fiberRoot 和 rootFiber。

  1. fiberRoot:整個應用的根節點(只能有一個)

  2. rootFiber:組件樹的根節點(可以有多個)

2.根據組件返回的JSX在內存中依次創建Fiber節點,并連接在一起構建形成Fiber樹,被稱為workInProgress Fiber樹。最后以 workInProgress 作為最新的渲染樹,fiberRoot 的 current 指針指向 workInProgress 使其變為 current Fiber 樹。到此完成初始化流程。

  1. workInProgress:正在內存中構建的 Fiber 樹稱為 workInProgress Fiber樹。在一次更新中,所有的更新都是發生在 workInProgress 樹上。在一次更新之后,workInProgress 樹上的狀態是最新的狀態,那么它將變成 current 樹用于渲染視圖。

  2. current:正在視圖層渲染的樹叫做 current 樹。

更新時

render階段,創建 dom,打上增刪改的 tag,等全部計算完之后,commit 階段一次性更新到 dom。

React原理實例分析

render階段

beginWork和completeWork階段會循環最新的jsx生成的虛擬dom,通過對比虛擬dom和current Fiber樹生成workinProgress Fiber樹。

beginWork

創建本次循環主體的子Fiber節點

  • mount(首屏渲染)時創建子Fiber節點,并返回改新建節點;

  • update時若不滿足復用條件,則與mount時一樣創建新的子fiber節點,并diff出相應的effTag掛在FIber節點上,并返回該新建節點;

  • updata時若滿足復用條件,且判斷仍需處理其子節點的后代,則返回復用后的子Fiber節點

  • updata時若滿足復用條件,且判斷不需繼續處理其子節點的后代,則直接返回null值;

completeWork

構建或更新DOM節點

  • 構建過程中,會自下而上將子節點插入到當前節點

  • 更新過程中,會計算DOM 節點的屬性,一旦屬性需要更新,會為DOM節點對應的workINProgress節點標記Update的effectTag

自下而上收集effectList,最終收集到root上

Diff到底是誰跟誰比?

Diff 是 vdom 和 current Fiber 對比,生成 workInProgressFiber

effectTag與effectList

render階段不會真正操作dom,只會創建dom然后打個effectTag的增刪改標記。commit階段就根據標記來更新dom就可以了。

但是commit階段要在遍歷一次fiber來查找有effectTag的節點,更新dom嗎?

當然沒問題,但是顯然很低效。完全可以把有 effectTag 的節點收集到一個鏈表里,然后 commit 階段直接遍歷這個鏈表就行了。這個鏈表叫做 effectList。

react 會在 commit 階段遍歷 effectList,根據 effectTag 來增刪改 dom。

這個隊列叫做 effectList。

commit階段

render階段找到變化的部分,創建dom,打上增刪改的tag,等全部計算完之后,commit階段一次性更新到dom。

before mutation階段(執行DOM操作前)

遍歷effectList,依次執行:

1.處理DOM節點渲染/刪除后的autoFocus、blur邏輯

2.調用getSnapshotBeforeUpdate生命周期鉤子

3.調度useEffect mutation階段(執行DOM操作)

遍歷 effectList 來更新 dom

layout階段(執行DOM操作后)

因為這個階段已經可以拿到布局信息了,會同步調用 useLayoutEffect 的回調函數。而且這個階段可以拿到新的 dom 節點,還會更新下 ref。

到此,相信大家對“React原理實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

清远市| 苗栗市| 环江| 习水县| 土默特右旗| 商河县| 闸北区| 同德县| 缙云县| 喀喇| 南澳县| 定襄县| 微山县| 永寿县| 灵石县| 成武县| 贵定县| 龙胜| 和平区| 瑞金市| 琼结县| 元朗区| 建阳市| 长葛市| 绵阳市| 绵竹市| 平塘县| 灵宝市| 乌海市| 泊头市| 郴州市| 镇平县| 长顺县| 调兵山市| 竹北市| 汕头市| 丰镇市| 甘泉县| 宁乡县| 青铜峡市| 荆门市|