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

溫馨提示×

溫馨提示×

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

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

React怎么更新流程驅動

發布時間:2023-04-15 11:05:50 來源:億速云 閱讀:96 作者:iii 欄目:開發技術

這篇文章主要介紹了React怎么更新流程驅動的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇React怎么更新流程驅動文章都會有所收獲,下面我們一起來看看吧。

一、react.createElement和ReactElement元素

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

舉個栗子:

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

轉換成

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內部到底做了什么?源碼位置

內部的實現其實很簡單,就是處理傳入的type/config/children等參數,再返回一個新的對象。

  • 從config中分離出特殊屬性 key 和 ref

  • 將普通屬性以及children添加到props中

  • 最后返回一個對象,這個對象我們稱之為ReactElement元素

ReactElement數據結構如下:

  const element = {
    $$typeof: REACT_ELEMENT_TYPE,
    type,
    key,
    ref,
    props,
  };
  • '$$typeof':ReactElement的標識

  • 'type':可能是'div' 'span'這樣的字符串標簽,也可以是個函數(函數式組件)、類(類組件)

  • 'key/ref/props': ReactElement的屬性

所以上述栗子的調用結果是下面的樹形結構:

{
    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'
                                        }
                                    }
                                ]
                    }
        }
    }
}

到這里就已經完成第一個和第二個小目標

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

所以16之后做的事情,就是依據上述的樹形結構進行重構,重構出來的fiber數據結構用于滿足異步渲染之需

二、雙緩存技術

上篇文章中已經介紹了fiber節點的數據結構,這里我們再介紹下fiberRoot以及rootFiber。 fiberRoot源碼位置

FiberRoot數據結構:

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: []
    };
  }
}

其中很多屬性我們暫時無視,后續涉及到的時候會詳細講解,這里重點關注節點的關系。 rootFiber的數據結構和普通的FiberNode節點區別不大,這里不再贅述~

整個React應用有且只有一個fiberRoot

整個應用中同時存在兩棵rootFiber樹

當前頁面對應的稱為currentFiber,另外一顆在內存中構建的稱為workInProgressFiber,它們通過alternate屬性連接。

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

當整個應用更新完成,fiberRoot會修改current指針指向內存中構建好的workInProgressFiber。

圖形描述如下:

React怎么更新流程驅動

三、React初始化的執行函數

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

    react.createRoot(root).render(<App/>)
  • root: 模版文件中的id為root的div

  • <App>: 整個應用的根組件

源碼簡化后的代碼如下:

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

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

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

react.createRoot()在內部會去創建整個應用唯一的fiberRoot和rootFiber,并進行關聯。(如上述圖形結構)

render內部執行的是updateContainer(),我們查看下內部實現:

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

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

而這個入口不僅僅在初始化執行函數中render調用會喚起,還有其他的方式:

  • 類組件中setState -> scheduleUpdateOnFiber()

  • 函數組件useState -> scheduleUpdateOnFiber()

關于“React怎么更新流程驅動”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“React怎么更新流程驅動”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

五大连池市| 冀州市| 抚松县| 永丰县| 进贤县| 晴隆县| 马尔康县| 宾阳县| 陕西省| 墨竹工卡县| 迁安市| 前郭尔| 江孜县| 禹城市| 锦州市| 永胜县| 罗山县| 潞城市| 峨眉山市| 湘阴县| 湾仔区| 铜山县| 瑞金市| 昭觉县| 富源县| 屏东市| 红桥区| 斗六市| 临沧市| 三门峡市| 遂平县| 会昌县| 康保县| 普安县| 桦川县| 高雄市| 济源市| 正镶白旗| 边坝县| 盖州市| 双流县|