最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

漸進式源碼解析React更新流程驅(qū)動

 更新時間:2023年04月14日 16:40:34   作者:龍崽崽  
這篇文章主要為大家介紹了漸進式源碼解析React更新流程驅(qū)動詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

前面兩篇文章介紹了fiber架構(gòu)和workLoop如何調(diào)度。但是缺了一塊非常重要的地方,那就是開發(fā)者寫的代碼是如何對接到上面流程的?

在日常開發(fā)中,我們只關(guān)心了如何寫組件,但是寫完的組件是如何被渲染到頁面當中?又是如何驅(qū)動更新流程?如果不知道這塊內(nèi)容,其實大家還是云里霧里的停留在概念層面。

所以這篇文章主要是從開發(fā)者角度闡述開發(fā)代碼->編譯->觸發(fā)更新流程的介紹。

這里的更新流程指schedule(調(diào)度)->reconciler(協(xié)調(diào))->commit (渲染)

老規(guī)矩還是先制定5個小目標:

  • react組件編譯成什么了?
  • reactElement元素是什么?
  • 什么是雙緩存技術(shù)?
  • react.createRoot().render()做了什么事情?
  • 還有哪些更新方式對接到目前的更新流程當中?

ok,我們一一解答:

一、react.createElement和ReactElement元素

首先我們書寫的函數(shù)式組件、類組件、jsx等代碼全部會被babel-react編譯成react.createElement()的調(diào)用或者jsx()調(diào)用(取決于react版本)。

舉個栗子:

<div>
    <ul>
    <li key='1'>1</li>
    <li key='2'>2</li>
    <li key='3'>3</li>
    </ul>
</div>

轉(zhuǎn)換成

React.createElement(
	'div',
	null,
	React.createElement(
		'ul',
		null,
		React.createElement(
                'li',
                {
                  key: '1'
                },
                '1'
		),
		React.createElement(
                'li',
                {
                 key: '2'
                },
                '2'
		),
		React.createElement(
                'li',
                {
                        key: '3'
                },
                '3'
		)
	)
);

接下來我們需要知道React.createElement內(nèi)部到底做了什么?源碼位置

內(nèi)部的實現(xiàn)其實很簡單,就是處理傳入的type/config/children等參數(shù),再返回一個新的對象。

  • 從config中分離出特殊屬性 key 和 ref
  • 將普通屬性以及children添加到props中
  • 最后返回一個對象,這個對象我們稱之為ReactElement元素

ReactElement數(shù)據(jù)結(jié)構(gòu)如下:

  const element = {
    $$typeof: REACT_ELEMENT_TYPE,
    type,
    key,
    ref,
    props,
  };
  • '$$typeof':ReactElement的標識
  • 'type':可能是'div' 'span'這樣的字符串標簽,也可以是個函數(shù)(函數(shù)式組件)、類(類組件)
  • 'key/ref/props': ReactElement的屬性

所以上述栗子的調(diào)用結(jié)果是下面的樹形結(jié)構(gòu):

{
    type: 'div',
    key: null,
    ref: null,
    props: {
        children: {
                    type: 'ul',
                    key: null,
                    ref: null,
                    props: {
                        children: [
                                    {
                                        type: 'li',
                                        key: null,
                                        ref: null,
                                        props: {
                                            children: '1'
                                        }
                                    },
                                    {
                                        type: 'li',
                                        key: null,
                                        ref: null,
                                        props: {
                                                children: '2'
                                        }
                                    },
                                    {
                                        type: 'li',
                                        key: null,
                                        ref: null,
                                        props: {
                                               children: '3'
                                        }
                                    }
                                ]
                    }
        }
    }
}

到這里就已經(jīng)完成第一個和第二個小目標

不過在這里要多提一下,上述的樹形結(jié)構(gòu),在react15版本及以前就可以直接拿來diff以及生成頁面,不過正如第一篇文章所說,這樣會遇到很大的問題(任務(wù)過重js執(zhí)行時間久,影響渲染)。

所以16之后做的事情,就是依據(jù)上述的樹形結(jié)構(gòu)進行重構(gòu),重構(gòu)出來的fiber數(shù)據(jù)結(jié)構(gòu)用于滿足異步渲染之需。

二、雙緩存技術(shù)

上篇文章中已經(jīng)介紹了fiber節(jié)點的數(shù)據(jù)結(jié)構(gòu),這里我們再介紹下fiberRoot以及rootFiber。 fiberRoot源碼位置

FiberRoot數(shù)據(jù)結(jié)構(gòu):

class FiberRootNode {
  current: FiberNode;
  container: any | null;
  finishedWork: FiberNode | null;
  pendingLanes: Lanes;
  finishedLane: Lane;
  pendingPassiveEffects: PendingPassiveEffects;
  constructor(container: any | null, hostRootFiber: FiberNode) {
    this.current = hostRootFiber;
    this.container = container;
    hostRootFiber.stateNode = this;
    this.finishedWork = null;
    this.pendingLanes = NoLanes;
    this.finishedLane = NoLane;
    this.pendingPassiveEffects = {
      unmount: [],
      update: []
    };
  }
}

其中很多屬性我們暫時無視,后續(xù)涉及到的時候會詳細講解,這里重點關(guān)注節(jié)點的關(guān)系。 rootFiber的數(shù)據(jù)結(jié)構(gòu)和普通的FiberNode節(jié)點區(qū)別不大,這里不再贅述~

整個React應(yīng)用有且只有一個fiberRoot

整個應(yīng)用中同時存在兩棵rootFiber樹

當前頁面對應(yīng)的稱為currentFiber,另外一顆在內(nèi)存中構(gòu)建的稱為workInProgressFiber,它們通過alternate屬性連接。

fiberRoot中的current指針指向了currentFiber樹。

當整個應(yīng)用更新完成,fiberRoot會修改current指針指向內(nèi)存中構(gòu)建好的workInProgressFiber。

圖形描述如下:

以上我們稱之為雙緩存技術(shù),當然這個技術(shù)不光用在react中,其他很多地方都有涉及,大家感興趣的話自行Google。

三、React初始化的執(zhí)行函數(shù)

在mount階段的時候,應(yīng)用是需要一個執(zhí)行函數(shù)的,而這個函數(shù)就是(源碼位置)

    react.createRoot(root).render(<App/>)
  • root: 模版文件中的id為root的div
  • <App>: 整個應(yīng)用的根組件

源碼簡化后的代碼如下:

    const createRoot = (container: Container) => {
            const root = createContainer(container);
            return {
                render(element: ReactElementType) {
                        return updateContainer(element, root);
                }
            };
    };

createRoot會返回一個對象,其中包含了render函數(shù),我們具體看看createContainer做了哪些事情。

const createContainer = (container: Container) => {
    // 創(chuàng)建rootFiber
    const hostRootFiber = new FiberNode(HostRoot, {}, null);
    // 創(chuàng)建fiberRoot
    const root = new FiberRootNode(container, hostRootFiber);
    hostRootFiber.updateQueue = createUpdateQueue();
    return root;
};

react.createRoot()在內(nèi)部會去創(chuàng)建整個應(yīng)用唯一的fiberRoot和rootFiber,并進行關(guān)聯(lián)。(如上述圖形結(jié)構(gòu))

render內(nèi)部執(zhí)行的是updateContainer(),我們查看下內(nèi)部實現(xiàn):

const updateContainer = (
	element: ReactElementType,
	root: FiberRootNode
) => {
	// mount時
	const hostRootFiber = root.current;
	// 添加update任務(wù)
	const lane = requestUpdateLane();
	const update = createUpdate<ReactElementType | null>(element, lane);
	enqueueUpdate(
		hostRootFiber?.updateQueue as UpdateQueue<ReactElementType | null>,
		update
	);
	scheduleUpdateOnFiber(hostRootFiber, lane);
	return element;
};

其中有很多地方我們此時無須關(guān)心,但是我們看到內(nèi)部調(diào)用了scheduleUpdateOnFiber, 而這個就是更新流程(schedule(調(diào)度)->reconciler(協(xié)調(diào))->commit (渲染))的入口。

而這個入口不僅僅在初始化執(zhí)行函數(shù)中render調(diào)用會喚起,還有其他的方式:

  • 類組件中setState -> scheduleUpdateOnFiber()
  • 函數(shù)組件useState -> scheduleUpdateOnFiber()

至此,我們知道了開發(fā)代碼->編譯->觸發(fā)更新流程的鏈路。

ok,以上就是文章的所有內(nèi)容了,我們總結(jié)下:

  • react組件會被編譯成react.createElement的調(diào)用,而調(diào)用結(jié)果是一顆樹形結(jié)構(gòu)。
  • react16之后會重構(gòu)增強這顆樹,變成fiber結(jié)構(gòu)。
  • 在react應(yīng)用中,使用了雙緩存技術(shù),用于更新。
  • mount階段的執(zhí)行函數(shù)(createRoot().render)會創(chuàng)建fiberRoot并且喚起更新流程。
  • 更新流程的喚起還有setState、useState等方式。

此篇文章完成了5個小目標,相信大家對整體的鏈路會更加清晰,后續(xù)的文章,會進一步深入到具體實現(xiàn)當中,敬請期待~

以上就是漸進式源碼解析React更新流程驅(qū)動的詳細內(nèi)容,更多關(guān)于React更新流程驅(qū)動的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談React組件之性能優(yōu)化

    淺談React組件之性能優(yōu)化

    這篇文章主要介紹了淺談React組件之性能優(yōu)化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • 詳解react中useCallback內(nèi)部是如何實現(xiàn)的

    詳解react中useCallback內(nèi)部是如何實現(xiàn)的

    前幾天有人在問在useCallback函數(shù)如果第二個參數(shù)為空數(shù)組, 為什么拿不到最新的state值,那么這一章就來分析一下useCallback內(nèi)部是如何實現(xiàn)的,感興趣的小伙伴跟著小編一起來學(xué)習(xí)吧
    2023-07-07
  • react中value與defaultValue的區(qū)別及說明

    react中value與defaultValue的區(qū)別及說明

    這篇文章主要介紹了react中value與defaultValue的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • React?在非組件環(huán)境切換路由的方法

    React?在非組件環(huán)境切換路由的方法

    這篇文章主要介紹了React?在非組件環(huán)境切換路由的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-10-10
  • react native 文字輪播的實現(xiàn)示例

    react native 文字輪播的實現(xiàn)示例

    這篇文章主要介紹了react native 文字輪播的實現(xiàn)示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • React Native設(shè)備信息查看調(diào)試詳解

    React Native設(shè)備信息查看調(diào)試詳解

    這篇文章主要為大家介紹了React Native設(shè)備信息查看調(diào)試詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • 一文帶你了解React中的函數(shù)組件

    一文帶你了解React中的函數(shù)組件

    函數(shù)式組件的基本意義就是,組件實際上是一個函數(shù),不是類,下面這篇文章主要給大家介紹了關(guān)于React中函數(shù)組件的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • React Native功能豐富的Toast通知庫

    React Native功能豐富的Toast通知庫

    這篇文章主要為大家介紹了React Native功能豐富的Toast通知庫使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React實現(xiàn)動效彈窗組件

    React實現(xiàn)動效彈窗組件

    最近在使用react開發(fā)項目,遇到這樣一個需求實現(xiàn)一個帶有動效的 React 彈窗組件,如果不考慮動效,很容易實現(xiàn),接下來小編通過本文給大家介紹React實現(xiàn)動效彈窗組件的實現(xiàn)代碼,一起看看吧
    2021-06-06
  • 淺談react+es6+webpack的基礎(chǔ)配置

    淺談react+es6+webpack的基礎(chǔ)配置

    下面小編就為大家?guī)硪黄獪\談react+es6+webpack的基礎(chǔ)配置。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08

最新評論

子长县| 嘉义市| 商洛市| 汝南县| 保靖县| 思茅市| 秭归县| 黄冈市| 横山县| 柏乡县| 湾仔区| 平顶山市| 资溪县| 杭州市| 卓资县| 宿松县| 怀集县| 沈阳市| 光泽县| 图们市| 株洲市| 天等县| 岐山县| 吉林市| 平谷区| 葵青区| 永川市| 湖州市| 安平县| 宣武区| 上饶县| 阿坝| 确山县| 郧西县| 正安县| 微山县| 集贤县| 葫芦岛市| 阳江市| 曲阳县| 周至县|