React 的Element 、Component 和 ReactClass 的概念

在使用 React 的時(shí)候,會(huì)出現(xiàn)幾個(gè)看起來(lái)相互混淆的概念,例如:Element,Class 和 Component。
我們先來(lái)看看 Element。

Element

Element 是后文 Class 的實(shí)例,React 通過解析每一個(gè)創(chuàng)建的 Element, 計(jì)算出需要對(duì) DOM 進(jìn)行的實(shí)際操作來(lái)完成渲染的。

React.render(
    React.createElement('div', {}, 'Hello, world!'), 
    document.body
);

代碼中的 React.createElement 創(chuàng)建了一個(gè)新的 div Componnet 的實(shí)例。第一個(gè)參數(shù) “div”是 React 預(yù)先定義好的。
第二個(gè)參數(shù){} 是需要傳入的 props,第三個(gè)參數(shù)是 "Child Element"。
當(dāng)你創(chuàng)建了第一個(gè) Element,其所有的“孩子”都會(huì)被自動(dòng)創(chuàng)建。
用 “Element” 來(lái)命名,應(yīng)該是遵從了 HTML Elements 的習(xí)慣。

Component 和 ReactClass

React 自己定義了好了大量的 Components,從 "div" 到 "svg",包含了幾乎所有 HTML Tags。
當(dāng)然,我們也可以創(chuàng)建自己的 Component,例如:

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

MyComponent 就是我們創(chuàng)建的 Component,至少需要包含一個(gè) render 方法的實(shí)現(xiàn)。隨后,我們就可以通過 React.createElement(MyComponent, {}, null) 來(lái)創(chuàng)建 “MyComponent” 的 “Element” 了。
這里最容易造成混淆的是,創(chuàng)建 “MyComponent” 方法名是 “React.createClass”,而不是 “React.createComponent”?!癱reateClass” 卻創(chuàng)建出了 “Component”,這是一個(gè)詭異的地方,雖然官方文檔定義 “createClass” 的返回類型為 “ReactClass”。
之前有過爭(zhēng)議 https://groups.google.com/forum/#!topic/reactjs/40dxGadNXeM.

Factory

為了簡(jiǎn)化 React.createElement 的調(diào)用語(yǔ)法,React.createFactory 被引入:

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

React.createFactory 的定義基本就是如下形式,Element 的類型被提前綁定了。

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

React.DOM.div 等都是預(yù)先定義好的 “Factory”?!癋actory” 用于創(chuàng)建特定 “ReactClass” 的 “Element”。

用 ES6 Class 代替 React.createClass

從 React 0.13 開始,可以使用 ES6 Class 代替 React.createClass 了。這應(yīng)該是今后推薦的方法,但是目前對(duì)于 mixins 還沒有提供官方的解決方案,你可以利用第三方的實(shí)現(xiàn) https://github.com/brigand/react-mixin.

class HelloMessage extends React.Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

React.Component 是基類(得,這里又變成了 Component了,其實(shí)準(zhǔn)確的命名可能是 ElementClass,或者 ComponentClass,不過這樣太長(zhǎng)了??)。

React.createClass 中的某些工作,可以直接在 ES6 Class 的構(gòu)造函數(shù)中來(lái)完成,例如:getInitialState 的工作可以被構(gòu)造函數(shù)所替代:

export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  tick() {
    this.setState({count: this.state.count + 1});
  }
  render() {
    return (
      <div onClick={this.tick.bind(this)}>
        Clicks: {this.state.count}
      </div>
    );
  }
}

propTypesgetDefaultTypes 這種靜態(tài)設(shè)置則可以變成類級(jí)別(不是類實(shí)例成員)的定義。

var ExampleComponent = React.createClass({ ... });
ExampleComponent.propTypes = {
 aStringProp: React.PropTypes.string
};
ExampleComponent.defaultProps = {
 aStringProp: ''
};

另外,原本通過 React.createClass 創(chuàng)建的 Component/Element 中的成員函數(shù)都是有 auto binding 能力的(缺省綁定到當(dāng)前 Element),那么使用 ES6 Class 則需要你自己綁定,或者使用 => (Fat Arrow)的聲明方式。Fat Arrow 會(huì)缺省將當(dāng)前 this 綁定到當(dāng)前類實(shí)例(ES6 和 CoffeeScript 一樣),但是不要對(duì) render 使用 =>。

class Counter extends React.Component {
  tick = () => {
    ...
  }
  ...
}

CoffeeScript 天生從這種新方式中得益,例如:

div = React.createFactory 'div'

class Counter extends React.Component
  @propTypes = initialCount: React.PropTypes.number
  @defaultProps = initialCount: 0

  constructor: (props) ->
    super props
    @state = count: props.initialCount

  tick: =>
    @setState count: @state.count + 1

  render: ->
    div onClick: @tick,
      'Clicks: ' + @state.count

CoffeeScript 一直是最簡(jiǎn)短的 JS。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個(gè)人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,945評(píng)論 1 18
  • GUIDS 第一章 為什么使用React? React 一個(gè)提供了用戶接口的JavaScript庫(kù)。 誕生于Fac...
    jplyue閱讀 3,712評(píng)論 1 11
  • 這篇文章比較偏基礎(chǔ),但是對(duì)入門 React 內(nèi)部機(jī)制和實(shí)現(xiàn)原理卻至關(guān)重要。算是為以后深入解讀的一個(gè)入門,如果您已經(jīng)...
    LucasHC閱讀 1,572評(píng)論 1 15
  • React的四個(gè)概念簡(jiǎn)單介紹 React主要有四個(gè)主要概念構(gòu)成,下面分別來(lái)介紹一下: Virtual DOM 虛擬...
    birdshome閱讀 4,451評(píng)論 1 5
  • 有這樣的一個(gè)問題: 最后的一句 用專業(yè)的詞概括是什么操作,組件調(diào)用還是什么? 有答“組件聲明”的,有答“組件調(diào)用的...
    uncle_charlie閱讀 2,895評(píng)論 0 3

友情鏈接更多精彩內(nèi)容