React 术语

===============================

在 React的术语当中,有5个核心的类型需要注意并且区分:

- [ReactElement / ReactElement Factory](#react-elements)
- [ReactNode](#react-nodes)
- [ReactComponent / ReactComponent Class](#react-components)

React Elements
--------------

首选对于 React 来说最主要的类型就是`ReactElement`, 它有4个属性,`type`, `props`, `key` 还有` ref`, 它没有方法和其他的 prototype.

你可以通过 `React.createElement`来创建.

```javascript
var root = React.createElement('div');
```
想要渲染一个新的树到 DOM 中,你需要将新创建的`ReactElement`作为参数传递给 `React.render`,之后它会返回一个 DOM 元素或者 svg 元素, `ReactElement`并不是 DOM 元素,它只是一个无状态不可修改的 javascript 对象.

```javascript
React.render(root, document.body);
```
想要添加一些 DOM 属性的时候,只需要传递一个 javascript 对象给第二个参数.

```javascript
var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);
```
如果用 JSX 语法是下面这样:

```javascript
var root = <ul className="my-list">
             <li>Text Content</li>
           </ul>;
React.render(root, document.body);
```

__Factories__ 

工厂方法

一个`ReactElement`-factory 其实就是一个函数,它会生成对应的一个对应的` type` 的 react 元素

```javascript
function createFactory(type){
  return React.createElement.bind(null, type);
}
```
它可以简写成下面这样:

```javascript
var div = React.createFactory('div'); //创建一个 div 的工厂方法
var root = div({ className: 'my-div' });
React.render(root, document.body);
```

React 同样已经内置了很多的工厂方法:

```javascript
var root = React.DOM.ul({ className: 'my-list' },
             React.DOM.li(null, 'Text Content')
           );
```

如果使用JSX语法,它已经为了实现了创建react element 这一步.

React Nodes
-----------

一个 react 的节点( react node) 可以是下面的一种:
- `ReactElement`
- `string` (aka `ReactText`)
- `number` (aka `ReactText`)
- Array of `ReactNode`s (aka `ReactFragment`)


他们通常作为属性来作为 react 元素的子节点出现.

React Components
----------------

你完成可以通过 react 元素来实现,但是为了能够体会到 react 的高级机制, 你应该使用` react 组件`来封装状态到这些元素中. 
一个 react 组件就是简单的 javascript 类:

```javascript
var MyComponent = React.createClass({
  render: function() {
    ...
  }
});
```
当调用构造函数的时候,它就会返回一个含有` render` 方法的对象:

```javascript
var component = new MyComponent(props); // never do this
```
除非在测试中使用, 一般不会使用上面的方式来获取组件的引用.
相反而是通过` createElement` 方法来讲`这个组件`作为参数使用,获取元素:

```javascript
var element = React.createElement(MyComponent);
```

或者使用 JSX:

```javascript
var element = <MyComponent />;
```
 接着通过` render` 方法,获取到这个组件的引用.
 
```javascript
var component = React.render(element, document.body);
```
以后再相同的条件下每次获取到的都是当前组件的相同引用:

```javascript
var componentA = React.render(<MyComponent />, document.body);
var componentB = React.render(<MyComponent />, document.body);
componentA === componentB; // true
```
这就是为什么不直接去拿到它的引用,而是通过 react 元素作为一个虚拟的组件在它被构造之前存在. 所以通过对比 `react 元素`是否变化来判断是否需要创建新的引用还是之前存在的.  react 组件必须要有这个`render` 方法, 它会返回一个 react 元素.这样就可以使得组件可以组合使用.最终渲染成为一个 dom树插入到 document 上.
 
 
Formal Type Definitions
-----------------------

__Entry Point__

```
React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
```

__Nodes and Elements__

```
type ReactNode = ReactElement | ReactFragment | ReactText;

type ReactElement = ReactComponentElement | ReactDOMElement;

type ReactDOMElement = {
  type : string,
  props : {
    children : ReactNodeList,
    className : string,
    etc.
  },
  key : string | boolean | number | null,
  ref : string | null
};

type ReactComponentElement<TProps> = {
  type : ReactClass<TProps>,
  props : TProps,
  key : string | boolean | number | null,
  ref : string | null
};

type ReactFragment = Array<ReactNode | ReactEmpty>;

type ReactNodeList = ReactNode | ReactEmpty;

type ReactText = string | number;

type ReactEmpty = null | undefined | boolean;
```

__Classes and Components__

```
type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;

type ReactComponent<TProps> = {
  props : TProps,
  render : () => ReactElement
};
```