鍍金池/ 教程/ HTML/ React (虛擬)DOM 術(shù)語
顯示數(shù)據(jù)
組件的引用
Controlled Input 值為 null 的情況
Reconciliation
子 props 的類型
組件的詳細(xì)說明和生命周期
傳遞 Props
特殊的非 DOM 屬性
組件 API
PureRenderMixin
雙向綁定輔助工具
瀏覽器中的工作原理
深入 JSX
表單組件
Dangerously Set innerHTML
入門
JSX 中的 If-Else
克隆組件
教程
更多的關(guān)于Refs
JSX 的 false 處理
高級(jí)性能
Mounting 后 componentWillReceiveProps 未被觸發(fā)
簡(jiǎn)介
測(cè)試工具集
JSX 陷阱
工具集成(ToolingIntegration)
公開組件功能
通過 AJAX 加載初始數(shù)據(jù)
事件系統(tǒng)
可復(fù)用組件
this.props.children undefined
不可變數(shù)據(jù)的輔助工具(Immutability Helpers)
動(dòng)態(tài)交互式用戶界面
組件的 DOM 事件監(jiān)聽
復(fù)合組件
動(dòng)畫
插件
JSX 展開屬性
行內(nèi)樣式
性能分析工具
類名操作
與其他類庫并行使用 React
鍵控的片段
標(biāo)簽和屬性支持
組件間的通信
React (虛擬)DOM 術(shù)語
JSX 根節(jié)點(diǎn)的最大數(shù)量
在樣式props中快速制定像素值
頂層 API
深入理解 React
自閉合標(biāo)簽
為什么使用 React?
getInitialState 里的 Props 是一個(gè)反模式
與 DOM 的差異

React (虛擬)DOM 術(shù)語

在 React 的術(shù)語中,有五個(gè)核心類型,區(qū)分它們是很重要的:

React 元素

React 中最主要的類型就是 ReactElement。它有四個(gè)屬性:type,props,keyref。它沒有方法,并且原型上什么都沒有。

可以通過 React.createElement 創(chuàng)建該類型的一個(gè)實(shí)例。

var root = React.createElement('div');

為了渲染一個(gè)新的樹形結(jié)構(gòu)到 DOM 中,你創(chuàng)建若干個(gè) ReactElement,然后傳給 React.render 作為第一個(gè)參數(shù),同時(shí)將第二個(gè)參數(shù)設(shè)為一個(gè)正規(guī)的 DOM 元素HTMLElement 或者 SVGElement)。不要混淆 ReactElement 實(shí)例和 DOM 元素 實(shí)例。一個(gè) ReactElement 實(shí)例是一個(gè)輕量的,無狀態(tài)的,不可變的,虛擬的 DOM 元素 的表示。是一個(gè)虛擬 DOM。

React.render(root, document.body);

要添加屬性到 DOM 元素,把屬性對(duì)象作為第二個(gè)參數(shù)傳入 React.render,把子級(jí)作為第三個(gè)參數(shù)傳給 React.render。

var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);

如果使用 React JSX 語法,這些 ReactElement 實(shí)例自動(dòng)創(chuàng)建。所以,如下代碼是等價(jià)的:

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

工廠

一個(gè) ReactElement 工廠就是一個(gè)簡(jiǎn)單的函數(shù),該函數(shù)生成一個(gè)帶有特殊 type 屬性的 ReactElement。React 有一個(gè)內(nèi)置的輔助方法用于創(chuàng)建工廠函數(shù)。事實(shí)上該方法就是這樣的:

function createFactory(type){
  return React.createElement.bind(null, type);
}

該函數(shù)能創(chuàng)建一個(gè)方便的短函數(shù),而不是總調(diào)用 React.createElement('div')。

var div = React.createFactory('div');
var root = div({ className: 'my-div' });
React.render(root, document.body);

React 已經(jīng)內(nèi)置了常用 HTML 標(biāo)簽的工廠函數(shù):

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

如果使用 JSX 語法,就不需要工廠函數(shù)了。JSX 已經(jīng)提供了一種方便的短函數(shù)來創(chuàng)建 ReactElement 實(shí)例。

React 節(jié)點(diǎn)

一個(gè) ReactNode 可以是:

  • ReactElement
  • string (又名 ReactText
  • number (又名 ReactText
  • ReactNode 實(shí)例數(shù)組 (又名 ReactFragment

這些被用作其它 ReactElement 實(shí)例的屬性,用于表示子級(jí)。實(shí)際上它們創(chuàng)建了一個(gè) ReactElement 實(shí)例樹。 (These are used as properties of other ReactElements to represent children. Effectively they create a tree of ReactElements.)

React 組件

在使用 React 開發(fā)中,可以僅使用 ReactElement 實(shí)例,但是,要充分利用 React,就要使用 ReactComponent 來封裝狀態(tài)化的組件。

一個(gè) ReactComponent 類就是一個(gè)簡(jiǎn)單的 JavaScript 類(或者說是“構(gòu)造函數(shù)”)。

var MyComponent = React.createClass({
  render: function() {
    ...
  }
});

當(dāng)該構(gòu)造函數(shù)調(diào)用的時(shí)候,應(yīng)該會(huì)返回一個(gè)對(duì)象,該對(duì)象至少帶有一個(gè) render 方法。該對(duì)象指向一個(gè) ReactComponent 實(shí)例。

var component = new MyComponent(props); // never do this

除非為了測(cè)試,正常情況下不要自己調(diào)用該構(gòu)造函數(shù)。React 幫你調(diào)用這個(gè)函數(shù)。

相反,把 ReactComponent 類傳給 createElement,就會(huì)得到一個(gè) ReactElement 實(shí)例。

var element = React.createElement(MyComponent);

或者使用 JSX:

var element = <MyComponent />;

當(dāng)該實(shí)例傳給 React.render 的時(shí)候,React 將會(huì)調(diào)用構(gòu)造函數(shù),然后創(chuàng)建并返回一個(gè) ReactComponent

var component = React.render(element, document.body);

如果一直用相同的 ReactElement 類型和相同的 DOM 元素容器調(diào)用 React.render,將會(huì)總是返回相同的實(shí)例。該實(shí)例是狀態(tài)化的。

var componentA = React.render(<MyComponent />, document.body);
var componentB = React.render(<MyComponent />, document.body);
componentA === componentB; // true

這就是為什么不應(yīng)該創(chuàng)建你自己的實(shí)例。相反,在創(chuàng)建之前,ReactElement 是一個(gè)虛擬的 ReactComponent。新舊 ReactElement 可以比對(duì),從而決定是創(chuàng)建一個(gè)新的 ReactComponent 實(shí)例還是重用已有的實(shí)例。

ReactComponentrender 方法應(yīng)該返回另一個(gè) ReactElement,這就允許組件被組裝。 (The render method of a ReactComponent is expected to return another ReactElement. This allows these components to be composed. Ultimately the render resolves into ReactElement with a string tag which instantiates a DOM Element instance and inserts it into the document.)

正式的類型定義

入口點(diǎn)(Entry Point)

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

節(jié)點(diǎn)和元素(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
};