React V17.0源碼 學習筆記(一)

ReactDOM.render 函數(shù)調(diào)用說明

說明 這里只討論web端初次調(diào)用關于hydrate的全部默認為false|undefinde管跺,不做解釋

ReactDOM.render(element,container,callback)

  • element reactElemtn
  • container HtmlElemnt
  • callback 掛載完成后的回調(diào)

作用: 渲染掛載的開始

  • 檢查 container 是否合法

  • 調(diào)用 legacyRenderSubtreeIntoContainer(null,elemrnt,container,false,callback)

legacyRenderSubtreeIntoContainer

  • parentComponent => null --------------- SSR 專用话肖,父結點
  • children => element ------------ 需要渲染的 ReactElemtn
  • container => container ---------- HtmlElment
  • forceHydrate => false -------------- SSR 專用逃片,通過 Hydrate 這里會是 true
  • callBack => callback ----------- 同上

作用:根據(jù) container 是否存在 root 區(qū)分初始化/更新槽地,創(chuàng)建或獲取 fiberRoot层释,進而啟動更新

從 container 取出 _reactRootContainer 作為 react 的一個根

const root = container._reactRootContainer

檢查 root 是否存在诊县,如果存在就是 Update座舍,如果不存在就是初始化

若 root 存在

從 root 中取出 fiberRoot

const fiberRoot = root._internalRoot

調(diào)用 updateContainer(children,fiberRoot,parentComponent,callBack)

注意:這里 callBack 會通過 getPublicRootInstance() 遞歸找到 fiberRoot 上第一個非 HTMlElement 結點,并將 callback 綁定在它上邊港令。

if (typeof callback === 'function') {
  const originalCallback = callback;
  callback = function() {
    const instance = getPublicRootInstance(fiberRoot);
    originalCallback.call(instance);
  };
}

若 root 不存在

調(diào)用 legacyCreateRootFromDOMContainer(contaiber,forceHydrate) 初始化 root淡喜。
將 root 賦值給 container._reactRootContainer,取出 root 中的_internalRoot 作為 fiberRoot秕磷。

調(diào)用 updateContainer(children,fiberRoot,parentComponent,callBack)。

//注意這里調(diào)用的時候拆火,是非批量的跳夭。因為是初始化的內(nèi)部掛載,所以需要使用非批量更新
unbatchedUpdates(() => {
  updateContainer(children, fiberRoot, parentComponent, callback);
});

// updateContainer() 就到了更新流程了们镜,這里不討論了^-^

legacyCreateRootFromDOMContainer

  • container --------------- HTMLElement
  • forceHydrate ------------ 同上

作用:清空 container,創(chuàng)建 root

  • 根據(jù) forceHydrate 和 container 上是否已經(jīng)被標記是一個 ReactContainer 來判斷是否需要清空 container(SSR 不需要清空币叹,但是 web 端初始化情況)
  • 創(chuàng)建一個 root 結點

shouleHydrate = forceHydrate && isReactContainer(contaiber)?{ hydrate:true }:undefinde

調(diào)用 createLegacyRoot(container,shouleHydrate)

createLegacyRoot

  • container --------------- HTMLElement
  • options:shouleHydrate --- 忽略

引入靜態(tài)變量 LegacyRoot = 0 ,作為 RootTag

調(diào)用 new ReactDOMBlockingRoot(container,LegacyRoot,options)

ReactDOMBlockingRoot

  • container --------------- HTMLElement
  • tag --------------------- root 的 tag 表示構建 root 的來源
  • options ----------------- 忽略

創(chuàng)建 RootImpl 模狭,賦值給 this._internalRoot 也就是 fiberRoot

this._internalRoot = createRootImpl(container, tag, options);

//注意:通過 ReactDOMBlockingRoot 創(chuàng)建的實例會自動實現(xiàn)兩個函數(shù) render 和 unmount
// 渲染根結點
render(children){
    root = this.\_internalRoot;
    updateContainer(children,root,null,null)
}
// 卸載根結點
unmount(){
    const root = this._internalRoot;
    const container = root.containerInfo;
    updateContainer(null, root, null, () => {
        // 從container中移除 __reactContainer 對應的fiber
        unmarkContainerAsRoot(container);
    });
}

createRootImpl

  • container --------------- HTMLElement
  • tag --------------------- root 的 tag 表示構建 root 的來源
  • options ----------------- 忽略

作用:

  • 根據(jù) container 創(chuàng)建 root
  • 標記 container 作為 root 的 current
  • 為 root 容器添加所有監(jiān)聽事件

根據(jù) container 創(chuàng)建 root

const root = createContainer(container, tag, hydrate, hydrationCallbacks);

標記 container 作為 root 的 current

// 為 container 字段 添加 __reactContainer 對應的 fiber
markContainerAsRoot(root.current, container);

為 root 容器添加所有監(jiān)聽事件

const rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
// 綁定事件監(jiān)聽颈抚,特殊處理selectionchange
listenToAllSupportedEvents(rootContainerElement);
createContainer -> createFiberRoot
  • containerInfo --------------- HTMLElement
  • tag ------------------------- root 的 tag 表示構建 root 的來源

作用:

  • 創(chuàng)建 root:FiberRoot

    root = new FiberRootNode(containerInfo,tag)

    -> root.containerInfo = containerInfo

    -> root.tag = tag

  • 創(chuàng)建 RootFiber:Fiber

    RootFiber = createHostRootFiber(tag);

    根據(jù) tag 生成一個 mode,web 初始化出來的 mode === NodeMode

    HostRoot = 3; // 表示創(chuàng)建的是 根結點

    調(diào)用 createFiber(HostRoot,null,null,mode)

    -> RootFiber.tag = HostRoot

    -> RootFiber.mode = mode

  • 形成一個閉環(huán)贩汉,將 root.current 指向 RootFiber锚赤,并將 root 作為 Fiber 的第一個 stateNode

    root.current = RootFiber

    RootFiber.stateNode = root

  • 初始化 RootFiber 的 UpdateQueue

    initializeUpdateQueue(RootFiber)

    ->queue.baseState = RootFiber.memoizedState

    ->RootFiber.updateQueus = queue

createFiber
  • tag ------------------------- fiber 的類型
  • penddingProps --------------- 外界數(shù)據(jù)
  • key ------------------------- 唯一表識
  • mode ------------------------ 基本都是 NodeMode

作用:
生成一個 FiberNode

FiberNode.tag = tag
FiberNode.penddingProps = penddingProps
FiberNode.mode=mode
FiberNode.key = key

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赐稽,一起剝皮案震驚了整個濱河市浑侥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌括丁,老刑警劉巖伶选,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異会宪,居然都是意外死亡掸鹅,警方通過查閱死者的電腦和手機拦赠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門荷鼠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來允乐,“玉大人,你說我怎么就攤上這事牍疏×墼桑” “怎么了厦滤?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵掏导,是天一觀的道長。 經(jīng)常有香客問我添瓷,道長仰坦,這世上最難降的妖魔是什么计雌? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任凿滤,我火速辦了婚禮,結果婚禮上眷蚓,老公的妹妹穿的比我還像新娘沙热。我一直安慰自己罢缸,他們只是感情好,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著息楔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圃泡。 梳的紋絲不亂的頭發(fā)上洞焙,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天拯啦,我揣著相機與錄音,去河邊找鬼唁情。 笑死甸鸟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的抢韭。 我是一名探鬼主播刻恭,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鳍贾,長吁一口氣:“原來是場噩夢啊……” “哼骑科!你這毒婦竟也來了咆爽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掰茶,失蹤者是張志新(化名)和其女友劉穎濒蒋,沒想到半個月后沪伙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體围橡,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡翁授,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了谍倦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖叼旋,靈堂內(nèi)的尸體忽然破棺而出夫植,到底是詐尸還是另有隱情,我是刑警寧澤辟拷,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站阐斜,受9級特大地震影響衫冻,放射性物質發(fā)生泄漏。R本人自食惡果不足惜谒出,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一隅俘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笤喳,春花似錦为居、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呜象,卻和暖如春膳凝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恭陡。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留永部,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子费奸,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容