国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

ReactDOM.render源碼解析-1

_Zhao / 985人閱讀

摘要:本文將對(duì)源碼做一個(gè)初步解析。首先在方法中校驗(yàn)參數(shù)是否合法,然后調(diào)用在中,調(diào)用拿到了的一個(gè)實(shí)例,調(diào)用拿到了,用于注入到,和作為返回值,調(diào)用開(kāi)始調(diào)度過(guò)程在中,首先清理了中的所有子節(jié)點(diǎn),然后了一個(gè)并返回是如何調(diào)度的是一個(gè)什么樣的類(lèi)的操作是在哪里

初步看了react-dom這個(gè)包的一些源碼,發(fā)現(xiàn)其比react包要復(fù)雜得多,react包中基本不存在跨包調(diào)用的情況,他所做的也僅僅是定義了ReactElement對(duì)象,封裝了對(duì)ReactElement的基本操作,而react-dom包存在復(fù)雜的函數(shù)調(diào)用。本文將對(duì)ReactDOM.render源碼做一個(gè)初步解析。
文章中如有不當(dāng)之處,歡迎交流指點(diǎn)。react版本16.8.2。在源碼添加的注釋在githubreact-source-learn。
前言

使用react時(shí)常常寫(xiě)類(lèi)似下面的代碼:

import ReactDOM from "react-dom";

ReactDOM.render(
  

Hello, world!

, document.getElementById("root") );

代碼1

這里導(dǎo)入的ReactDOM就是packages/react-dom/client/ReactDOM.js中所導(dǎo)出的對(duì)象。從文檔可見(jiàn)ReactDOM對(duì)象有如下幾個(gè)方法:(ps:從源碼看其實(shí)還有很多其他方法)

render()

hydrate()

unmountComponentAtNode()

findDOMNode()

createPortal()

本文只介紹render()方法

代碼分析

render方法定義如下:

   render(
    element: React$Element,
    container: DOMContainer,
    callback: ?Function,
  ) {
    invariant(
      // 1
      isValidContainer(container),
      "Target container is not a DOM element.",
    );
    if (__DEV__) {
      warningWithoutStack(
        !container._reactHasBeenPassedToCreateRootDEV,
        "You are calling ReactDOM.render() on a container that was previously " +
          "passed to ReactDOM.%s(). This is not supported. " +
          "Did you mean to call root.render(element)?",
        enableStableConcurrentModeAPIs ? "createRoot" : "unstable_createRoot",
      );
    }
    // 2
    return legacyRenderSubtreeIntoContainer(
      null,
      element,
      container,
      false,
      callback,
    );
  },

代碼2

render方法接收兩個(gè)必選參數(shù)可一個(gè)可選參數(shù),結(jié)合代碼1的調(diào)用可知,element是一個(gè)ReactElement對(duì)象, container是一個(gè)dom節(jié)點(diǎn),callback在上面的代碼1并沒(méi)有指定,他是一個(gè)可選函數(shù)。

這個(gè)render方法做的事情比較簡(jiǎn)單,一是校驗(yàn)container參數(shù),二是調(diào)用legacyRenderSubtreeIntoContainer方法并返回。

接下來(lái)是legacyRenderSubtreeIntoContainer

// 刪除了第一次調(diào)ReactDOM.render不會(huì)走的分支
function legacyRenderSubtreeIntoContainer(
  parentComponent: ?React$Component, // ReactDOM.render 是null
  children: ReactNodeList, // 是一個(gè)ReactElement , ReactDOM.render是第一個(gè)參數(shù)
  container: DOMContainer, // 是一個(gè)dom節(jié)點(diǎn), ReactDOM.render是第二個(gè)參數(shù)
  forceHydrate: boolean, // ReactDOM.render 是false
  callback: ?Function, // ReactDOM.render 是 第三個(gè)參數(shù)
) {
  if (__DEV__) {
    topLevelUpdateWarnings(container);
  }

  // TODO: Without `any` type, Flow says "Property cannot be accessed on any
  // member of intersection type." Whyyyyyy.
  // 根據(jù)type知道, Root type是個(gè)對(duì)象,包含
  // render方法
  // unmount方法
  // legacy_renderSubtreeIntoContainer 方法
  // createBatch 方法
  // _internalRoot屬性
  let root: Root = (container._reactRootContainer: any);
  if (!root) { // ReactDOM.render調(diào)用時(shí)走這里
      // Initial mount
      // 調(diào)用 legacyCreateRootFromDOMContainer 拿 Root
      root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
      container,
      forceHydrate, // ReactDOM.render是false
    );

    // 在callback加參數(shù)
    if (typeof callback === "function") {
      const originalCallback = callback;
      callback = function() {
        const instance = getPublicRootInstance(root._internalRoot);
        originalCallback.call(instance);
      };
    }
    // Initial mount should not be batched.
    // 這個(gè)是packages/react-reconciler/ReactFiberScheduler.js中的方法
    // TOLEARN: 這個(gè)里邊應(yīng)該是一些調(diào)度過(guò)程, 后續(xù)再看
    unbatchedUpdates(() => {
      if (parentComponent != null) {
        root.legacy_renderSubtreeIntoContainer(
          parentComponent,
          children,
          callback,
        );
      } else { // ReactDOM.render方法走這里
        // 這里的root.render 返回的是一個(gè)叫Work的東西, TOLEARN,這個(gè)Work后面再做了解
        root.render(children, callback);
      }
    });
  }
  // getPublicRootInstance是/packages/react-reconciler/ReactFiberReconciler.js中的方法
  // 關(guān)于他是返回的一個(gè)什么東西, 后面再看, 總之他是我ReactDOM.render方法回調(diào)函數(shù)的一個(gè)參數(shù),
  // 也是返回值
  return getPublicRootInstance(root._internalRoot);
}

legacyRenderSubtreeIntoContainer在第一次render時(shí)做了如下事情:

調(diào)用legacyCreateRootFromDOMContainer拿到一個(gè)ReactRoot的實(shí)例

在callback中注入一個(gè)參數(shù)instance

調(diào)用unbatchedUpdates開(kāi)始一輪調(diào)度過(guò)程,這個(gè)是猜的

返回instance

關(guān)于instance的獲取是調(diào)用的getPublicRootInstance,getPublicRootInstance是/packages/react-reconciler/ReactFiberReconciler.js中的方法,后面再研究

關(guān)于unbatchedUpdates, 這個(gè)東西是這個(gè)是packages/react-reconciler/ReactFiberScheduler.js中的方法,簡(jiǎn)單看了看還沒(méi)太明白

接下來(lái)看一下ReactRoot實(shí)例的獲取

// 刪除了__DEV__分支的代碼
// 若需要清理container的子節(jié)點(diǎn),清理, 然后new ReactRoot并返回
function legacyCreateRootFromDOMContainer(
  container: DOMContainer,  // dom節(jié)點(diǎn)
  forceHydrate: boolean, // false render
): Root {
  // 是否不需要清理container的子元素, 第一次render是false, 即需要清理
  const shouldHydrate =
    forceHydrate || shouldHydrateDueToLegacyHeuristic(container); // 第一次調(diào)用時(shí)為false
  // First clear any existing content.
  if (!shouldHydrate) { // 第一次render走這里
    let warned = false;
    let rootSibling;
    // 這里將container的子元素都清理掉了
    while ((rootSibling = container.lastChild)) {
      container.removeChild(rootSibling);
    }
  }
  // Legacy roots are not async by default.
  const isConcurrent = false;
  return new ReactRoot(container, isConcurrent, shouldHydrate);
}

這個(gè)方法比較簡(jiǎn)單,在第一次調(diào)用ReactDOM.render時(shí),shouldHydrate會(huì)是false,所以會(huì)走到if (!shouldHydrate) 分支里,將container節(jié)點(diǎn)的所有子節(jié)點(diǎn)都清理掉,最后是new 了一個(gè)ReactRoot作為返回值,關(guān)于ReactRoot等內(nèi)容將放到后面的文章分析。

小結(jié)

以上是ReactDOM.render的函數(shù)調(diào)用示意圖。

首先在render方法中校驗(yàn)container參數(shù)是否合法,然后調(diào)用legacyRenderSubtreeIntoContainer

在legacyRenderSubtreeIntoContainer中, 調(diào)用legacyCreateRootFromDOMContainer拿到了ReactRoot的一個(gè)實(shí)例,調(diào)用getPublicRootInstance拿到了instance,用于注入到callback,和作為返回值,調(diào)用unbatchedUpdates開(kāi)始調(diào)度過(guò)程

在legacyCreateRootFromDOMContainer中,首先清理了container中的所有子節(jié)點(diǎn),然后new了一個(gè)ReactRoot并返回

TODO

unbatchedUpdates是如何調(diào)度的

ReactRoot是一個(gè)什么樣的類(lèi)

dom的操作是在哪里

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/103511.html

相關(guān)文章

  • react解析: render的FiberRoot(三)

    摘要:查看創(chuàng)建核心函數(shù)源碼行調(diào)用函數(shù)創(chuàng)建是相關(guān),不用管源碼行這個(gè)指的是調(diào)用創(chuàng)建,下面我們將會(huì)說(shuō)到對(duì)象源碼行源碼行函數(shù)中,首先創(chuàng)建了一個(gè),然后又創(chuàng)建了一個(gè),它們兩者還是相互引用。 感謝 yck: 剖析 React 源碼解析,本篇文章是在讀完他的文章的基礎(chǔ)上,將他的文章進(jìn)行拆解和加工,加入我自己的一下理解和例子,便于大家理解。覺(jué)得yck寫(xiě)的真的很棒 。React 版本為 16.8.6,關(guān)于源碼的...

    muddyway 評(píng)論0 收藏0
  • React源碼解析ReactDOM.render()

    摘要:一更新的方式有三種渲染接下來(lái),我們就來(lái)看下源碼二作用在提供的里渲染一個(gè)元素,并返回對(duì)該組件的引用常見(jiàn)的用法是這個(gè)官網(wǎng)網(wǎng)址源碼服務(wù)端使用方法渲染節(jié)點(diǎn)是讓服務(wù)端盡可能復(fù)用節(jié)點(diǎn),提高性能元素容器應(yīng)用渲染結(jié)束后,調(diào)用的函數(shù)錯(cuò)誤抓取方法本質(zhì)是返回 showImg(https://segmentfault.com/img/remote/1460000020064414?w=1240&h=641);...

    iKcamp 評(píng)論0 收藏0
  • React源碼解析ReactDOM.render源碼

    摘要:的創(chuàng)建組件,其實(shí)根源還是調(diào)用了編譯之后一般寫(xiě)法建議用來(lái)進(jìn)行源碼的跟蹤鏈接從源碼角度來(lái)看創(chuàng)建一個(gè)組件的過(guò)程中發(fā)生了什么。 https://github.com/jimwmg/Rea... 1 React.createClass( ) var HelloWorld = React.createClass({ render : function(){ return ...

    joywek 評(píng)論0 收藏0
  • ReactRoot與ReactWork源碼分析

    摘要:在中調(diào)用獲得了的實(shí)例,然后調(diào)用其中的回調(diào)函數(shù)中調(diào)用了方法。這個(gè)類(lèi)主要介紹其構(gòu)造函數(shù)和方法,構(gòu)造函數(shù)是時(shí)調(diào)用的,方法是的回調(diào)函數(shù)中使用的。這個(gè)將在下一篇分析。另外,方法是在的回調(diào)函數(shù)中調(diào)用的,也是一個(gè)參與后面調(diào)度的關(guān)鍵。 在ReactDOM.render源碼解析-1中介紹了第一次render的基本過(guò)程的一部分,其中產(chǎn)生了ReactRoot和ReactWork兩個(gè)類(lèi)的實(shí)例。本文介紹下Rea...

    macg0406 評(píng)論0 收藏0
  • 剖析 React 源碼render 流程(二)

    摘要:就是,如果你不了解這個(gè)的話可以閱讀下相關(guān)文檔,是應(yīng)用初始化時(shí)就會(huì)生成的一個(gè)變量,值也是,并且這個(gè)值不會(huì)在后期再被改變。這是我的剖析 React 源碼的第三篇文章,如果你沒(méi)有閱讀過(guò)之前的文章,請(qǐng)務(wù)必先閱讀一下 第一篇文章 中提到的一些注意事項(xiàng),能幫助你更好地閱讀源碼。 文章相關(guān)資料 React 16.8.6 源碼中文注釋?zhuān)@個(gè)鏈接是文章的核心,文中的具體代碼及代碼行數(shù)都是依托于這個(gè)倉(cāng)庫(kù) 熱身...

    My_Oh_My 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<