美文网首页
React V17.0源码 学习笔记(一)

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

作者: 郭仙人不是闲人 | 来源:发表于2020-12-11 11:56 被阅读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

    相关文章

      网友评论

          本文标题:React V17.0源码 学习笔记(一)

          本文链接:https://www.haomeiwen.com/subject/lmljgktx.html