React V17.0源码 学习笔记(一)

ReactDOM.render 函数调用说明

说明 这里只讨论web端初次调用关于hydrate的全部默认为false|undefinde,不做解释

ReactDOM.render(element,container,callback)

  • element reactElemtn
  • container HtmlElemnt
  • callback 挂载完成后的回调

作用: 渲染挂载的开始

  • 检查 container 是否合法

  • 调用 legacyRenderSubtreeIntoContainer(null,elemrnt,container,false,callback)

legacyRenderSubtreeIntoContainer

  • parentComponent => null --------------- SSR 专用,父结点
  • children => element ------------ 需要渲染的 ReactElemtn
  • container => container ---------- HtmlElment
  • forceHydrate => false -------------- SSR 专用,通过 Hydrate 这里会是 true
  • callBack => callback ----------- 同上

作用:根据 container 是否存在 root 区分初始化/更新,创建或获取 fiberRoot,进而启动更新

从 container 取出 _reactRootContainer 作为 react 的一个根

const root = container._reactRootContainer

检查 root 是否存在,如果存在就是 Update,如果不存在就是初始化

若 root 存在

从 root 中取出 fiberRoot

const fiberRoot = root._internalRoot

调用 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 不存在

调用 legacyCreateRootFromDOMContainer(contaiber,forceHydrate) 初始化 root。
将 root 赋值给 container._reactRootContainer,取出 root 中的_internalRoot 作为 fiberRoot。

调用 updateContainer(children,fiberRoot,parentComponent,callBack)。

//注意这里调用的时候,是非批量的。因为是初始化的内部挂载,所以需要使用非批量更新
unbatchedUpdates(() => {
  updateContainer(children, fiberRoot, parentComponent, callback);
});

// updateContainer() 就到了更新流程了,这里不讨论了^-^

legacyCreateRootFromDOMContainer

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

作用:清空 container,创建 root

  • 根据 forceHydrate 和 container 上是否已经被标记是一个 ReactContainer 来判断是否需要清空 container(SSR 不需要清空,但是 web 端初始化情况)
  • 创建一个 root 结点

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

调用 createLegacyRoot(container,shouleHydrate)

createLegacyRoot

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

引入静态变量 LegacyRoot = 0 ,作为 RootTag

调用 new ReactDOMBlockingRoot(container,LegacyRoot,options)

ReactDOMBlockingRoot

  • container --------------- HTMLElement
  • tag --------------------- root 的 tag 表示构建 root 的来源
  • options ----------------- 忽略

创建 RootImpl ,赋值给 this._internalRoot 也就是 fiberRoot

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

//注意:通过 ReactDOMBlockingRoot 创建的实例会自动实现两个函数 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 ----------------- 忽略

作用:

  • 根据 container 创建 root
  • 标记 container 作为 root 的 current
  • 为 root 容器添加所有监听事件

根据 container 创建 root

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

标记 container 作为 root 的 current

// 为 container 字段 添加 __reactContainer 对应的 fiber
markContainerAsRoot(root.current, container);

为 root 容器添加所有监听事件

const rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
// 绑定事件监听,特殊处理selectionchange
listenToAllSupportedEvents(rootContainerElement);
createContainer -> createFiberRoot
  • containerInfo --------------- HTMLElement
  • tag ------------------------- root 的 tag 表示构建 root 的来源

作用:

  • 创建 root:FiberRoot

    root = new FiberRootNode(containerInfo,tag)

    -> root.containerInfo = containerInfo

    -> root.tag = tag

  • 创建 RootFiber:Fiber

    RootFiber = createHostRootFiber(tag);

    根据 tag 生成一个 mode,web 初始化出来的 mode === NodeMode

    HostRoot = 3; // 表示创建的是 根结点

    调用 createFiber(HostRoot,null,null,mode)

    -> RootFiber.tag = HostRoot

    -> RootFiber.mode = mode

  • 形成一个闭环,将 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 --------------- 外界数据
  • key ------------------------- 唯一表识
  • mode ------------------------ 基本都是 NodeMode

作用:
生成一个 FiberNode

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容