React 源碼解析之ReactElement

本小書大部分內(nèi)容來自作者 Jokcy 的 《React 源碼解析》: https://react.jokcy.me/

本文已同步在我的博客: http://ruizhengyun.cn/blog/post/f5de7c02.html

感謝 Jokcy 讓我深度了解 React戒努。如他所說蚊丐,在決定閱讀 React 源碼時(shí)認(rèn)為不會(huì)是一件很難的事,但是真正開始閱讀之后才發(fā)現(xiàn)瞬场,事情沒那么簡單,因?yàn)樾枰銐虻哪托摹⒛軌颡?dú)立思考和靜下心來(因?yàn)槟銜?huì)碰到之前編碼沒有見過的寫法和概念等等)。

ReactElement.js 整體部分

// 保留的 props
const RESERVED_PROPS = {
  key: true,
  ref: true,
  __self: true,
  __source: true,
};

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // 此標(biāo)記允許我們將其唯一標(biāo)識(shí)為React元素
    $$typeof: REACT_ELEMENT_TYPE,
    
    // 屬于元素的內(nèi)置屬性
    type: type,
    key: key,
    ref: ref,
    props: props,

    // 記錄負(fù)責(zé)創(chuàng)建此元素的組件牲览。
    _owner: owner,
  };

  if (__DEV__) {/*...*/}

  return element;
} 

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

  // Reserved names are extracted(提取保留名稱)
  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;
    }
    if (hasValidKey(config)) {
      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];
      }
    }
  }

  const childrenLength = arguments.length - 2;
  if( childrenLength === 1) {
    props.children = children;
  } else {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) { /*...*/ }
    props.children = childArray;
  }

  return ReactElement(
    type,
    key,
    ref,
    self,
    source, 
    ReactCurrentOwner.current,
    props
  );
}

分析 createElement 函數(shù)

function createElement(type, config, children) {}
  • 該函數(shù)接收 3 個(gè)參數(shù),分別是 type, config, children桑驱;
  • 調(diào)用 ReactElement竭恬,ReactElement 內(nèi)部返回一個(gè)對(duì)象 element

config 邏輯

if(config != null){
  if(hasValidRef(config)) {
    ref = config.ref;
  }
  if(hasValidKey(config)){
    key = '' + config.key;
  }
  self = config.__self === undefined ? null : config.__self;
  source = config.__source === undefined ? null : config.__source;
  // 剩余的屬性將添加到新的 props 對(duì)象中
  for (propName in config) {
    if(hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
      props[propName] = config[propName];
    }
  }
}

這段代碼做了

  • 對(duì) refkey 做了驗(yàn)證(對(duì)于這種校驗(yàn)方法無需內(nèi)部實(shí)現(xiàn)熬的,保持干凈痊硕,也便于閱讀);
  • 遍歷 config 把內(nèi)建的幾個(gè)屬性(剔除原型鏈上的屬性和規(guī)定要剔除的屬性)丟到 props 中去押框;

children 邏輯

const childrenLength = arguments.length - 2;
if( childrenLength === 1) {
  props.children = children;
} else {
  const childArray = Array(childrenLength);
  for (let i = 0; i < childrenLength; i++) {
    childArray[i] = arguments[i + 2];
  }
  if (__DEV__) { /*...*/ }
  props.children = childArray;
}

第一行可以看出岔绸,取出第二個(gè)參數(shù)后的參數(shù),然后判斷長度是否 > 1:

  • > 1 就代表有多個(gè) children橡伞,這個(gè)時(shí)候 props.children 會(huì)是一個(gè)數(shù)組盒揉, 所以后面在對(duì) props.children 進(jìn)行遍歷的時(shí)候需要注意它是否是數(shù)組,當(dāng)然你也可以利用 React.Children 中的 API兑徘,下文中也會(huì)對(duì) React.Children 中的 API 進(jìn)行講解刚盈;
  • === 1 就是一個(gè)對(duì)象;

返回值

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // 此標(biāo)記允許我們將其唯一標(biāo)識(shí)為React元素
    $$type: REACT_ELEMENT_TYPE,
    
    // 屬于元素的內(nèi)置屬性
    type: type,
    key: key,
    ref: ref,
    props: props,

    // 記錄負(fù)責(zé)創(chuàng)建此元素的組件挂脑。
    _owner: owner,
  };

  if (__DEV__) {/*...*/}

  return element;
} 

核心就是通過 $$type 來識(shí)別這是個(gè) ReactElement藕漱,后會(huì)看到很多類似的類型欲侮。

注意:通過 JSX 寫的 <APP /> 代表 ReactElementAPP 代表 React Component (組件)肋联。

這章節(jié)的內(nèi)容可以繪制成的流程

createElement 流程

你可以

上一篇:React 源碼解析之總覽

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末威蕉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子橄仍,更是在濱河造成了極大的恐慌韧涨,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侮繁,死亡現(xiàn)場(chǎng)離奇詭異虑粥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鼎天,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門舀奶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暑竟,“玉大人斋射,你說我怎么就攤上這事〉纾” “怎么了罗岖?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長腹躁。 經(jīng)常有香客問我桑包,道長,這世上最難降的妖魔是什么纺非? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任哑了,我火速辦了婚禮,結(jié)果婚禮上烧颖,老公的妹妹穿的比我還像新娘弱左。我一直安慰自己,他們只是感情好炕淮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布拆火。 她就那樣靜靜地躺著,像睡著了一般涂圆。 火紅的嫁衣襯著肌膚如雪们镜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天润歉,我揣著相機(jī)與錄音模狭,去河邊找鬼。 笑死踩衩,一個(gè)胖子當(dāng)著我的面吹牛嚼鹉,可吹牛的內(nèi)容都是我干的邪意。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼反砌,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼雾鬼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宴树,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤策菜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后酒贬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體又憨,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年锭吨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蠢莺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡零如,死狀恐怖躏将,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情考蕾,我是刑警寧澤祸憋,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肖卧,受9級(jí)特大地震影響蚯窥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塞帐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一拦赠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葵姥,春花似錦荷鼠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牡辽,卻和暖如春喳篇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背态辛。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工麸澜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奏黑。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓炊邦,卻偏偏與公主長得像编矾,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子馁害,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容