React Element是React构建应用的最小单位的构建块,React常常说到的虚拟DOM指的就是它。

JSX

React Element的创建可以使用React提供的JSX语法来书写。JSX是React提供的一种模板语法糖,让开发者可以直接在js文件里写模板语法,就像写js语句一样。

1
const element = <h1>Hello, world!</h1>;

JSX使用Babel转化后,会发现JSX其实是使用React.createElement生成的React Element。本质上,它是一个对象,用于描述要渲染到页面上的节点信息。

1
const element = React.create

ReactElement

React 提供了createElemnt函数,用于生成React Element,也就是虚拟DOM。

在React/lib/ReactElement.js中存放着createElement的相关代码,CreateElement的结构如下。

React/lib/ReactElement.jsReactElement.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14

var ReactElement = function (type, key, ref, self, source, owner, props) {

}

ReactElement.createElement = function (type, config, children) {};

ReactElement.createFactory = function (type) {};

ReactElement.cloneAndReplaceKey = function (oldElement, newKey) {};

ReactElement.cloneElement = function (element, config, children) {};

ReactElement.isValidElement = function (object) {}

ReactElement执行返回React Element,是一个对象,结构如下:

1
2
3
4
5
6
7
8
{
$$typeof: REACT_ELEMENT_TYPE, // symbol ,标识React Element
type: type, // 元素类型,string,function
key: key, // 标识元素的key
ref: ref, // 存储element的ref
props: props, // Element的属性
_owner: _owner // 所属React Component
}

ReactElement.createElement

React/lib/ReactElement.jsReactElement.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ReactElement.createElement = function (type, config, children) {
var propName;

var props = {};

var key = null;
var ref = null;
var self = null;
var source = null;

// 获取key,ref,self,source,props
// key,ref,self,source不存放在props上
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];
}
}
}

// 获取props.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];
}
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];
}
}
}

// 创建React Element
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
};

ReactCurrentOwner是一个对象,只有current一个属性,用于存储当前正在构建的Component所属的Component。ReactCurrentOwner.current主要在react-dom的ReactCompositeComponent中被赋值。

ReactElement.createFactory

React/lib/ReactElement.jsReactElement.js
1
2
3
4
5
6
7
ReactElement.createFactory = function (type) {
var factory = ReactElement.createElement.bind(null, type);
factory.type = type;

// 返回type确定的ReactElement创建函数
return factory;
}