最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React createElement方法使用原理分析介紹

 更新時(shí)間:2022年09月01日 14:27:45   作者:搞前端的小菜  
這篇文章主要為大家介紹了React的createElement方法源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

摘要

在上一篇說(shuō)過(guò),React創(chuàng)建元素有兩種方式:

第一種是通過(guò)JSX方式創(chuàng)建,第二種是通過(guò)React.createElement方法創(chuàng)建。但是通過(guò)JSX創(chuàng)建React元素的方式,最終也會(huì)經(jīng)過(guò)babel進(jìn)行轉(zhuǎn)換,再用React.createElement進(jìn)行元素創(chuàng)建。

而這一篇文章,主要是講一下React.createElement是如何創(chuàng)建React元素的。

1.創(chuàng)建方法

為了了解React.createElement這個(gè)方法,我們自己手動(dòng)去實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的。

OK,首先我們通過(guò)React.createElement方法創(chuàng)建一個(gè)React元素,并且打印出來(lái):

    const b = React.createElement('div',{data: '1234'},'oneTwo')
    console.log(b);

打印出來(lái)的結(jié)果為:

所以,如果我們要實(shí)現(xiàn)出來(lái)React.createElement這個(gè)方法,定義的時(shí)候我們可以這么寫(xiě):

function createElement(type, config, children){
  let props = {}
  let myType = ''
  let key = ''
  let ref = ''
  return {
    $$typeOf: 'react.element',
    type: myType,
    props,
    key,
    ref
  }
}

這里我們不管**$$typeOf**這個(gè)變量,只考慮其他的變量,最終返回的對(duì)象應(yīng)該是這個(gè)數(shù)據(jù)結(jié)構(gòu)。

2.處理type

好了,方法的定義已經(jīng)寫(xiě)完了。針對(duì)于傳進(jìn)來(lái)的這三個(gè)參數(shù),我們一個(gè)一個(gè)看。

第一個(gè)參數(shù)type,它代表的是創(chuàng)建React元素的類(lèi)型。

這里面可以是傳統(tǒng)的HTML元素,例如div,h1,span等標(biāo)簽。

也可以是一個(gè)React組件(注意這里哦)。

而React創(chuàng)建組件又有兩種方式,所以type的值,有三種數(shù)據(jù)類(lèi)型:

(1)字符串:例如"div",“h1”,“span”,"p"等標(biāo)簽

(2)函數(shù):通過(guò)函數(shù)的方式創(chuàng)建React組件

(3)類(lèi):通過(guò)class的方式創(chuàng)建React組件

而這個(gè)時(shí)候就有一個(gè)問(wèn)題!

class Demo {
}
typeof Demo

上面的值應(yīng)該為什么呢?答案是function,所以在這里我們只需要考慮type為string和function兩種類(lèi)型即可。

所以我們可以寫(xiě)一個(gè)判斷類(lèi)型的方法:

function isValidElementType(type){
  if(typeof type === 'string' || typeof type === 'function'){
    return true;
  }
  return false;
}

在我們的主方法里面引用:

function createElement(type, config, children){
  let props = {}
  let myType = ''
  let key = ''
  let ref = ''
  if(isValidElementType(type)){
    myType = type;
  }
  return {
    $$typeOf: 'react.element',
    type: myType,
    props,
    key,
    ref
  }
}

3.處理config

對(duì)于React.createElement方法的第二個(gè)參數(shù),接收看一個(gè)對(duì)象。而對(duì)象下所有的屬性,都會(huì)被放在props里面。

這句話(huà)對(duì)不對(duì)呢?其實(shí)也不是很對(duì),是有特例的,如果在這個(gè)對(duì)象下,有key或者ref這兩個(gè)屬性。它是不會(huì)被放在props里面的,而是直接賦值給key和ref

Ok,有了上面的話(huà),我們就可以對(duì)config進(jìn)行處理了:

  if(config != null){
    if(config.ref){
      ref = config.ref
    }
    if(config.key){
      key = config.key
    }
    for(let propName in config){
      if(!(['ref','key'].includes(propName))){
        props[propName] = config[propName]
      }
    }
  }

我們只需要把config的key和ref分別給到我們返回對(duì)象里面的key和ref。再便利一下config,拿出來(lái)的屬性和值把key和ref排除。最終我們的config屬性就處理好了。

4.處理children

最后一步就是處理children屬性了。而React.createElement方法的第三個(gè)參數(shù),也可以是第四個(gè)參數(shù)(就是后面的所有參數(shù))。都可以為字符串,或者是React元素。

這里的React元素我們不管它是通過(guò)JSX創(chuàng)建的,還是通過(guò)React.createElement方法創(chuàng)建的都可以

而參數(shù)的情況分兩種:

第一種是只有三個(gè)參數(shù),也就是children為一個(gè)值。這個(gè)時(shí)候props里面的children就是該字符串。

第二種是參數(shù)大于三個(gè),這個(gè)時(shí)候,props里面的children是一個(gè)數(shù)組,數(shù)組里的元素就是后面的所有參數(shù)。

OK,有了上面的基礎(chǔ),就可以對(duì)children進(jìn)行處理了:

  let childrenLength = arguments.length - 2
  if(childrenLength === 1){
    props.children = children
  }else if(childrenLength > 1){
    let children = new Array(childrenLength)
    for(let i = 0;i<childrenLength;i++){
      children[i] = arguments[i+2]
    }
    props.children = children
  }

這里通過(guò)arguments來(lái)判斷參數(shù)的個(gè)數(shù),進(jìn)而確定分支條件。

然后再根據(jù)情況,確定props里的children。

最后再貼上完整的createElement方法(簡(jiǎn)易版):

function createElement(type, config, children){
  let props = {}
  let myType = ''
  let key = ''
  let ref = ''
  if(isValidElementType(type)){
    myType = type;
  }
  if(config != null){
    if(config.ref){
      ref = config.ref
    }
    if(config.key){
      key = config.key
    }
    for(let propName in config){
      if(!(['ref','key'].includes(propName))){
        props[propName] = config[propName]
      }
    }
  }
  let childrenLength = arguments.length - 2
  if(childrenLength === 1){
    props.children = children
  }else if(childrenLength > 1){
    let children = new Array(childrenLength)
    for(let i = 0;i<childrenLength;i++){
      children[i] = arguments[i+2]
    }
    props.children = children
  }
  return {
    $$typeOf: 'react.element',
    type: myType,
    props,
    key,
    ref
  }
}

5.對(duì)比真正的React.createElement源碼

OK,上面只是實(shí)現(xiàn)了一個(gè)比較簡(jiǎn)單的React.createElement方法,但是懂了其中的過(guò)程,我們就可以看一下真正的React.createElement源碼:

isValidElementType方法

function isValidElementType(type) {
  if (typeof type === 'string' || typeof type === 'function') {
    return true;
  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
  if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing  || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden  || type === REACT_OFFSCREEN_TYPE || enableScopeAPI  || enableCacheElement  || enableTransitionTracing ) {
    return true;
  }
  if (typeof type === 'object' && type !== null) {
    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
    // types supported by any Flight configuration anywhere since
    // we don't know which Flight build this will end up being used
    // with.
    type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
      return true;
    }
  }
  return false;
}

這里面也主要就是判斷type的類(lèi)型,不過(guò)判斷情況多了幾種React自帶的元素類(lèi)型。

createElement方法

function createElement(type, config, children) {
  var propName; // Reserved names are extracted
  var props = {};
  var key = null;
  var ref = null;
  var self = null;
  var source = null;
  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;
      {
        warnIfStringRefCannotBeAutoConverted(config);
      }
    }
    if (hasValidKey(config)) {
      {
        checkKeyStringCoercion(config.key);
      }
      key = '' + config.key;
    }
    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object
    for (propName in config) {
      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
        props[propName] = config[propName];
      }
    }
  } // Children can be more than one argument, and those are transferred onto
  // the newly allocated props object.
  var childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    var childArray = Array(childrenLength);
    for (var i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }

    {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  } // Resolve default props
  if (type && type.defaultProps) {
    var defaultProps = type.defaultProps;

    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  {
    if (key || ref) {
      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
      if (key) {
        defineKeyPropWarningGetter(props, displayName);
      }
      if (ref) {
        defineRefPropWarningGetter(props, displayName);
      }
    }
  }
  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
};

這個(gè)方法主要是對(duì)config和children進(jìn)行處理。

其余的部分就不粘過(guò)來(lái)了,對(duì)源碼感興趣的可以自己打斷點(diǎn)嘗試一哈!

到此這篇關(guān)于React createElement方法使用原理分析介紹的文章就介紹到這了,更多相關(guān)React createElement內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React源碼分析之useCallback與useMemo及useContext詳解

    React源碼分析之useCallback與useMemo及useContext詳解

    這篇文章主要介紹了React useCallback與useMemo及useContext源碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-11-11
  • React服務(wù)端渲染和同構(gòu)的實(shí)現(xiàn)

    React服務(wù)端渲染和同構(gòu)的實(shí)現(xiàn)

    本文主要介紹了React服務(wù)端渲染和同構(gòu)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • react如何修改循環(huán)數(shù)組對(duì)象的數(shù)據(jù)

    react如何修改循環(huán)數(shù)組對(duì)象的數(shù)據(jù)

    這篇文章主要介紹了react如何修改循環(huán)數(shù)組對(duì)象的數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • react-redux中connect()方法詳細(xì)解析

    react-redux中connect()方法詳細(xì)解析

    connect()是React-redux中的核心方法之一,它將react組件預(yù)redux中的Store真正連接在一起,下面這篇文章主要給大家介紹了react-redux中connect()方法的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-05-05
  • reactrouter dom庫(kù)作用小結(jié)

    reactrouter dom庫(kù)作用小結(jié)

    `react-router-dom`是React應(yīng)用中用于實(shí)現(xiàn)頁(yè)面導(dǎo)航、嵌套路由、布局管理以及代碼分割和懶加載的重要庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • react  Suspense工作原理解析

    react  Suspense工作原理解析

    這篇文章主要為大家介紹了react  Suspense工作原理解析以及基本應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • React渲染機(jī)制及相關(guān)優(yōu)化方案

    React渲染機(jī)制及相關(guān)優(yōu)化方案

    這篇文章主要介紹了react中的渲染機(jī)制以及相關(guān)的優(yōu)化方案,內(nèi)容包括react渲染步驟、concurrent機(jī)制以及產(chǎn)生作用的機(jī)會(huì),簡(jiǎn)單模擬實(shí)現(xiàn) concurrent mode,基于作業(yè)調(diào)度優(yōu)先級(jí)的思路進(jìn)行項(xiàng)目?jī)?yōu)化的兩個(gè)hooks,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2023-07-07
  • React中Redux Hooks的使用詳解

    React中Redux Hooks的使用詳解

    這篇文章主要介紹了React Redux Hooks的使用詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • react導(dǎo)出excel文件的四種方式

    react導(dǎo)出excel文件的四種方式

    本文主要介紹了react導(dǎo)出excel文件的四種方式,主要包括原生js導(dǎo)出,使用?js-export-excel,使用xlsx導(dǎo)出, 使用react-html-table-to-excel,感興趣的可以了解一下
    2023-11-11
  • React?Native采用Hermes熱更新打包方案詳解

    React?Native采用Hermes熱更新打包方案詳解

    這篇文章主要介紹了React?Native采用Hermes熱更新打包實(shí)戰(zhàn),在傳統(tǒng)的熱更新方案中,我們實(shí)現(xiàn)熱更新需要借助code-push開(kāi)源方案,包括熱更新包的發(fā)布兩種方式詳解,感興趣的朋友一起看看吧
    2022-05-05

最新評(píng)論

噶尔县| 镇平县| 五莲县| 孝感市| 滕州市| 佛坪县| 滁州市| 灵璧县| 青浦区| 阳高县| 文山县| 临朐县| 海伦市| 京山县| 沙田区| 从江县| 宜州市| 定南县| 峨山| 雷波县| 阳高县| 永清县| 宣恩县| 青冈县| 奉贤区| 军事| 敦化市| 色达县| 锦州市| 莱芜市| 扶沟县| 曲麻莱县| 阳春市| 宜州市| 高碑店市| 蒙阴县| 榆社县| 玉溪市| 海阳市| 土默特右旗| 马龙县|