2014-12-01 58 views
7

注意:此帖已發佈到當時React不支持ES6(v12)。React和ES6繼承

我有一個ES6類:

class BaseClass { 
    getInitialState(){ 
     return {message: 'Hello!'}; 
    } 

    render() { 
     return (
      <div> 
       <div>{this.state.message}</div> 
      </div> 
     ) 
    } 
} 

我可以在ES6使用這個表達式(來源:react ES6 browserify)出口

export default React.createClass(BaseClass.prototype) 

這工作得很好。現在我想用ES6繼承致以BaseClass類:

class ExtendedClass extends BaseClass{ 
    getInitialState(){ 
     return {message: "Hello! I'm an extension"}; 
    } 
} 

但是當我打電話React.createClassExtendedClass類,我得到了以下異常:

Invariant Violation: ReactCompositeComponentInterface: You are attempting to define `constructor` on your component more than once. This conflict may be due to a mixin. 

我知道陣營0.13被認爲更ES6友好,但有什麼辦法來處理?

編輯:

我使用Traceur編譯我ES6類。爲ExtendedClass輸出看起來像:

function ExtendedClass() { 
    "use strict"; 
    if (BaseClass !== null) { 
    BaseClass.apply(this, arguments); 
    } 
} 
for (BaseClass____Key in BaseClass) { 
    if (BaseClass.hasOwnProperty(BaseClass____Key)) { 
     ExtendedClass[BaseClass____Key] = BaseClass[BaseClass____Key]; 
    } 
    } 
    ____SuperProtoOfBaseClass = BaseClass === null ? null : BaseClass.prototype; 
    ExtendedClass.prototype = Object.create(____SuperProtoOfBaseClass); 
    ExtendedClass.prototype.constructor = ExtendedClass; 
    ExtendedClass.__superConstructor__ = BaseClass; 
    ExtendedClass.prototype.getInitialState = function() { 
    "use strict"; 
    return {message: "Hello! I'm an extension"}; 
    }; 
    React.createClass(ExtendedClass.prototype); 
+0

getInitialState不應與ES6代碼中使用。相反,在構造函數中設置你的初始狀態,'constructor(props){super(props); this.state = {message:'Hello!'}}' – widged 2015-08-04 02:19:00

+0

此帖已發佈在React不支持ES6(v12)的時間。它不再相關。當然,使用React v13一切正常,並且不需要使用提到的解決方法。 – JBE 2015-08-04 14:19:50

回答

1

這裏是我已經找到了解決辦法:

裏面React.js庫,我已經更新了ReactCompositeComponentInterface添加自定義策略constructor(據我所知有沒有辦法可以定製的「接口」正常):在ExtendedClass

var ReactCompositeComponentInterface = { 

/** 
* An array of Mixin objects to include when defining your component. 
* 
* @type {array} 
* @optional 
*/ 
mixins: SpecPolicy.DEFINE_MANY, 

/** 
* Custom policy for 'constructor' 
*/ 
constructor: SpecPolicy.DEFINE_MANY, 

    ... 

} 

然後,你必須重新定義每個方法,即使你不自定義他們:

class ExtendedClass extends BaseClass{ 
    getInitialState(){ 
     return {message: "Hello! I'm an extension"}; 
    } 
    /** required */ 
    render(){ 
     return super.render(); 
    } 
} 

我對這個骯髒的解決方案不滿意,但它會完成等待0.13版本的工作,希望能解決這些問題。

6

關於在ES6中編寫ReactJS有一篇很棒的文章。

http://ilikekillnerds.com/2015/02/developing-react-js-components-using-es6/

反正使用ES6,當你不使用React.createClass。您只需創建延伸React.Component的類

同樣在ES6中,您沒有getInitialState而不是defaultProps。它被替換爲使用this.state內部構造函數。

看看這個例子。假設您有擴展卡組件的卡組件和歡迎面板。

的代碼如下:

卡組件:

import React , { Component } from 'react' 
class Card extends Component { 
    constructor(props){ 
    super(props); 
    } 

    render() { 
    return (
     <div className="card"> 
      <div className="card__content"> 
      <label>{this.props.content}</label> 
      </div> 
     </div> 
    ) 
    } 

    initPanel(el,content){ 
    React.render(<Card content={content} />, el); 
    } 
} 

export default Card; 

歡迎面板組件:

import React from 'react'; 
import Card from 'components/card.component'; 

class WelcomePanel extends Card { 
    constructor(props){ 
    super(props); 
    this.state = { 
     content: "Welcome Panel", 
     index: 0 
    } 
    } 

    componentClicked(){ 
    this.setState({content: "Component Clicked", index: this.state.index + 1}) 
    } 

    render() { 
    return (
     <div className="welcome-panel" onClick={this.componentClicked.bind(this)}> 
     <Card content={`${this.state.content} ${this.state.index > 0 ? this.state.index : ''} ${this.state.index > 0 ? 'times' : ''} `} /> 
     </div> 
    ) 
    } 

    initPanel(el,content){ 
    React.render(<WelcomePanel />, el); 
    } 
} 

export default { Class: WelcomePanel }