【react源碼】理解jsx從深刻了解createElement源碼開始

此文章源碼解讀版本 react16.6
做者:starkwang
歡迎關注訂閱號:rd-hub
如需轉載請標明做者和出處

開始

從一個最簡單的jsx開始

2018-10-28-16-15-18

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<h2 style={{ "color": "#53cde2" }}>hi stark wang</h2>, document.getElementById('root'));

bable 會轉譯成(編譯原理會另有篇幅橡樹)react

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(React.createElement(
  'h2',
  { style: { "color": "#53cde2" } },
  'hi stark wang'
), document.getElementById('root'));

編譯 在這隻勾選 一個react選項(爲了保證閱讀體驗,編譯後仍是es6)

2018-10-28-16-20-44

React.createElement

在此咱們看到在ReactDOM.render()函數裏面有兩個參數,下面咱們來看看React.createElement()源碼

createElement() 源碼以下:es6

2018-10-28-16-43-06

分析 createElement()源碼

function createElement(type, config, children) {

}
從函數來看,三個參數:type,config,children

參數 type

表示類型好比咱們傳入的是 <h2 style={{ "color": "#53cde2" }}>hi stark wang</h2> 此時的type就是 h2dom

爲了增長文章的嚴謹,我專門在源碼裏面作了調試

2018-10-28-16-54-38

參數 config

config 就是dom屬性: style={{ "color": "#53cde2" }}

2018-10-28-16-59-49

參數 children

children 就是咱們在dom裏面的內容了
2018-10-28-17-02-15

把config的屬性放在props上面

2018-10-28-17-32-29

檢查是否有ref 和 key 源碼 (上面用到的源碼)
function hasValidRef(config) {
  {
    if (hasOwnProperty.call(config, 'ref')) {
      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
      if (getter && getter.isReactWarning) {
        return false;
      }
    }
  }
  return config.ref !== undefined;
}

function hasValidKey(config) {
  {
    if (hasOwnProperty.call(config, 'key')) {
      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
      if (getter && getter.isReactWarning) {
        return false;
      }
    }
  }
  return config.key !== undefined;
}

把dom裏面的內容放在props上面

// 經過arguments 的長度來判斷dom裏面的內容
  var childrenLength = arguments.length - 2; // 2 :表明默認的 type 和 config,減去就是 children了
  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;
  }
若是dom屬性內容爲 <h2>hi stark {shudong} {rdhub.cn} {starkwang}</h2> 則參數爲 8個
默認有有兩個,剩下都是 children 因此剩下有6個分別是
  • {shudong}
  • ''
  • {rdhub.cn}
  • ''
  • {starkwang}
每一個變量中間的隔得內容都算一個參數

2018-10-28-17-42-46

type.defaultProps 到 props

if (type && type.defaultProps) {
    var defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

返回一個構造函數 ReactElement

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

總結一下createElement()作了哪些事情

  1. 把 config裏的內容拷入props
  2. 把 children 到 props.children
  3. 把 type.defaultProps 到 props
  4. 返回一個構造函數 ReactElement

關於我

https://www.yuque.com/rdhub/a...
2018-10-20-19-06-01函數

相關文章
相關標籤/搜索