23
此文章源码解读版本 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 会转译成(编译原理会另有篇幅橡树)

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() 源码如下:

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就是 h2

为了增加文章的严谨,我专门在源码里面做了调试

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


西树先森
7.1k 声望926 粉丝

从事开发多年,前端、后端(go、Python、php)、服务架构都有涉猎,经历过大公司、创业公司,擅长前端及公司技术选型。