2015-06-23 43 views
0

有沒有人有過使用React組件作爲純JS對象而不是惱人的ES6類的經驗,並且已棄用.createClass方法。將組件作爲純JS對象進行響應?

也許你有一些工廠功能或類似的共享的例子?

謝謝!

+1

'React.Component'是一個普通的JavaScript函數,因爲ES6只是語法糖 - 簽名是'功能ReactComponent(道具,背景)' –

+0

這裏有點不清楚你的意思。你的意思是代碼通過jsx和es6轉譯器運行後的JavaScript最終結果? – fraxture

回答

3

React.Component是一個普通的javascript函數,因爲es6類是圍繞它們的語法糖。所以我們可以使用我們喜歡的任何es5類概念,我只是借用骨幹extend方法在這裏:

// From backbone 
var extend = function(protoProps) { 
    var parent = this; 
    var child; 

    var extendObj = function(obj1, obj2) { 
     for (var i in obj1) { 
      if (obj1.hasOwnProperty(i)) { 
      obj2[i] = obj1[i]; 
      } 
     } 
    }; 

    // The constructor function for the new subclass is either defined by you 
    // (the "constructor" property in your `extend` definition), or defaulted 
    // by us to simply call the parent constructor. 
    if (protoProps && hasOwnProperty.call(protoProps, 'constructor')) { 
     child = protoProps.constructor; 
    } else { 
     child = function() { return parent.apply(this, arguments); }; 
    } 

    // Set the prototype chain to inherit from `parent`, without calling 
    // `parent` constructor function. 
    var Surrogate = function(){ this.constructor = child; }; 
    Surrogate.prototype = parent.prototype; 
    child.prototype = new Surrogate; 

    // Add prototype properties (instance properties) to the subclass, 
    // if supplied. 
    if (protoProps) extendObj(child.prototype, protoProps); 

    // Set a convenience property in case the parent's prototype is needed 
    // later. 
    child.__super__ = parent.prototype; 

    return child; 
}; 

React.Component.extend = extend; 

然後,我們可以創建一個組件是這樣的:

var MyComponent = React.Component.extend({ 
    constructor: function() { 
     console.log('hello from react component'); 

     this.setState({ 
      open: false 
     }); 

     React.Component.apply(this, arguments); 
    } 
}); 

new MyComponent(); 

這只是一個例子(未經測試),你可以做任何一種原型實現,你既然喜歡這只是一個正常的功能。如果您搜索「es5繼承」,您應該可以應用任何這些解決方案。

+0

謝謝,這對於瞭解'React.Component(道具,上下文)'簽名很有用。我還在尋找一種方法來更新'render'方法,例如'render({props,state},setState)',以便在組件中無處不在地討厭'this'。 – Kosmetika

0

我想我的回答遲到了。但是我使用基於JavaScript的傳統原型對象製作了很多React組件。如果你喜歡基於原型的對象,你可以試試下面的:)

一個簡單的例子:

第1步:安裝inherits模塊

npm install inherits -S 

然後,

const React = require('react'); // switch to import, if you like 
const is = require('prop-types'); 
const inherits = require('inherits'); 

inherits(MyComponent, React.Component); 
module.exports = MyComponent; 
var prototype = MyComponent.prototype; 

MyComponent.defaultProps = { 
    onClick: function(){ } 
}; 

MyComponent.propTypes = { 
    onClick: is.func, 
    href: is.string, 
    label: is.string 
} 

function MyComponent(props) { 
    React.Component.call(this, props); 
    this.state = {clicked: false}; 
} 

prototype.render = function() { 
    return (
    <a href={this.props.href} onClick={this.props.onClick}> 
     {this.props.label} 
    </a>) 
} 

// for debugging purpose, set NODE_ENV production, will remove the following 
if (process.env.NODE_ENV !== 'production') { 
    MyComponent.displayName = 'MyComponent'; 
} 

更先進的方法來分離你的擔憂是將你的方法放在不同的文件中。 (通常,保護或私有方法,幾個月或幾年後不需要知道的東西。)然後,將它們合併到原型對象上。你可以通過以下方式來完成。

... 
const _proto = require('./prototype'); //make a prototype folder, and merge all files' methods into one. 

... 
var prototype = Object.assign(MyComponent.prototype, _proto); 

或者,你想使你的組件作爲EventEmitter,你可以像下面:

.... 
const _proto = require('./prototype'); 
const Emitter = require('component-emitter'); 

.... 
var prototype = Object.assign(MyComponent.prototype, _proto, Emitter.prototype); 

function MyComponent(props) { 
    React.Component.call(this, props); 

    this.onClick = _=> this.emit("click"); 
} 

prototype.render = function() { 
    return <a href={this.props.href} onClick={this.onClick}>{this.props.label}</a> 
} 

在原型文件夾,您可以編寫如下:

指數。 JS

Object.assign(exports, require('./styles.js').prototype) 

styles.js

const prototype = exports.prototype = {}; 

prototype.prepareStyles = function() { 

    var styles = Object.defineProperties({}, { 
    wrapper: { get: _=> ({ 
     backgroundColor: '#333' 
    })}, 

    inner: {get: _=> { 
     return this.state.clicked ? {...} : {...} 
    }} 
    }); 

    Object.defineProperties(this, { 
    styles: {get: _=> styles} 
    }) 
} 
//All the methods are prefixed by prototype, so it is easy to cut and paste the methods around different files, when you want to hide some methods or move some methods to be with the constructor to make your component more easy to read. 

然後,在主文件中。只需調用方法準備的所有樣式:

function MyComponent(props) { 
    React.Component.call(this, props); 

    this.prepareStyles(); 
} 

和使用的樣式,

prototype.render = function() { 
    return ( 
     <div style={this.styles.wrapper}> 
     <div styles={this.styles.inner}>hello world</div> 
     </div> 
) 
} 
相關問題