react 元素,即JSX語法。react
const Nav, Profile; // 輸入(JSX): const app = <Nav color="blue"><Profile>click</Profile></Nav>; // 通過react編譯解釋以後,輸出(JavaScript): const app = React.createElement( Nav, {color:"blue"}, React.createElement(Profile, null, "click") );
能夠看到,咱們平時在react 中寫的語法,最終是調用React的createElement方法。
那麼createElement作了什麼呢?
直接查看源碼,一探究竟。app
好,開始實現code
React.createElement = function(type, config, children) { var propName; var props = {}; var key = null; var ref = null; var self = null; var source = null; if (config !== null) { if (hasValidKey(config)) { key = '' + config.key; } if (hasValidRef(config)) { ref = config.ref; } self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; for(propName in config) { if (hasOwnerProperty.call(config, propName) && !REACT_RESERVED_PROPS.hasOwnProperty(propName) { props[propName] = config[propName]; } } // children 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 (__DEV__) { if (Object.freeze) { Object.freeze(childArray); } } props.children = childArray; } // default Props if (type && type.defaultProps) { var defaultProps = type.defaultProps; for(propName in defaultProps) { if (props[propName] === undefined) { props[propName] = defaultProps[propName]; } } } // key || ref if (__DEV__) { if (key || ref) { if (typeOf config.$$typeOf === undefined || props.$$typeOf !== REACT_ELEMENT_TYPE) { 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 ); };
在上述代碼中能夠看到,createElement 最終返回的是一個ReactElement 對象,那ReactElement又是什麼對象呢?
實現步驟:component
ReactElement = function(type, key, ref, self, source, owner, props) { var element = { $$typeOf: REACT_ELEMENT_TYPE, type: type, key: key, ref: ref, // record the component responsible for creating the element _owner: owner, }; if (__DEV__) { // self && source only dev props element._store = {}; Object.defineProperty(element._store, 'validated', { writable: false, configurable: false, enumerable: false, value: false, }); Object.defineProperty(element, '_self', { writable: false, configurable: false, enumerable: false, value: self, }); Object.defineProperty(element, '_source', { writable: false, configurable: false, enumerable: false, value: source, }); if (Object.freeze) { Object.freeze(element.props); Object.freeze(element); } } return element; }
其中校驗key 和 self 是不是有效的方法爲:
(由於兩種是類似的,因此只列出一種)對象
var defineKeyPropWarningGetter = function(props, displayName) { var warnAboutAccessingKey = function() { if (!specialPropKeyWarningShown) { specialPropKeyWarningShow = true; warn(false, '%s, `ref` prop 。。。。', displayName); } } warnAboutAccessingKey.isReactWarning = true; Object.defineProperty(props, 'key', { get: warnAboutAccessingKey configurable: true, }) }; var hasValidKey = function(config) { if (__DEV__) { if (hasOwnerProperty.call(config, 'key')) { var getter = Object.getOwnPropertyDescriptor(config, 'key').get; if (getter && getter.isReactWarning) { return false; } } } return config.key !== undefined; }
其餘一些定義:ip
var REACT_ELEMENT_TYPE = (typeOf symbol && symbol.for && symbol.for('react.element')) || 0xeac7; /** * Keeps track of the current owner. * * The current owner is the component who should own any components that are * currently being constructed. */ var ReactCurrentOwner = { current: (null: null | ReactInstance | Fiber) // 這是什麼寫法??? } var REACT_RESERVED_PROPS = { key: true, ref: true, __self: true, __source: true, };
react源碼:/16.0.0-rc.2/src/isomorphic/classic/element/ReactElement.js
陳屹:《深刻react技術棧》ci