JSX

JSX

JSX是一種JavaScript的語(yǔ)法擴(kuò)展,運(yùn)用于React架構(gòu)中,其格式比較像是模版語(yǔ)言,但事實(shí)上完全是在JavaScript內(nèi)部實(shí)現(xiàn)的。我們能在React中直接編寫JSX代碼,得益于babel的轉(zhuǎn)譯,比如:

<div className='box'>
  <span>test</span>
  <span>{test}</span>
</div>

轉(zhuǎn)譯后:

/*#__PURE__*/
React.createElement("div", {
  className: "box"
}, /*#__PURE__*/React.createElement("span", null, "test"), /*#__PURE__*/React.createElement("span", null, test));

也就是說轉(zhuǎn)譯之后默認(rèn)會(huì)調(diào)用React.createElement()方法。這也側(cè)面說明了即使你再寫函數(shù)組件的時(shí)候沒有顯示地引用React,也必須先import React from 'react'

React.createElement()

這里精簡(jiǎn)了方法的實(shí)現(xiàn)原理,并作了相關(guān)注釋


const hasOwnProperty = Object.prototype.hasOwnProperty;

/*
*@param {*} type 元素類型,或是組件類名
*@param {*} config 元素屬性
*@param {*} children 子元素
*/

function createElement(type, config, children) {
  let propName;

  const props = {};

  //循環(huán)遍歷config中的屬性,并添加為props的屬性
  if (config != null) {
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        !RESERVED_PROPS.hasOwnProperty(propName)
      ) {
        props[propName] = config[propName];
      }
    }
  }

  //這段代碼主要是為了將子元素作為一個(gè)數(shù)組,保存到props的children屬性中。
  //雖然形參只有一個(gè)children,但實(shí)參可能有多個(gè),除了第一個(gè)是type和第二個(gè)是config,其他都是children,即實(shí)參列表的長(zhǎng)度減2就是children的個(gè)數(shù)
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    //如果只有一個(gè)children,直接賦值
    props.children = children;
  } else if (childrenLength > 1) {
    //如果children大于一個(gè),就把所有children保存到數(shù)組中,賦值給props.children
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  }

  //這里主要針對(duì)type是class類名的情況
  //JSX中以大寫字母開頭的組件會(huì)被認(rèn)為是自定義組件,以小寫字母開頭的會(huì)被認(rèn)為是標(biāo)簽。自定義組件可能會(huì)有defaultProps
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

  //ReactElement可以認(rèn)為是包含了這些屬性的一個(gè)對(duì)象,類似這樣的結(jié)構(gòu)
  /* {
    type:'div',
    props:{
      className:'box',
      children:{
        type:'span',
        props:{
          children:'test'
        }
      }
    }
  } */
  return ReactElement(
    type,
    props,
  );
}

小結(jié):JSX轉(zhuǎn)譯之后其實(shí)是一個(gè)ReactElement對(duì)象,虛擬DOM其實(shí)就是這樣的一個(gè)JS對(duì)象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容