将组件作为普通JS对象进行反应?

时间:2015-06-23 08:55:08

标签: javascript class reactjs javascript-objects ecmascript-6

是否有人使用React组件作为普通的JS对象而不是恼人的ES6类和不推荐的.createClass方法。

也许您有一些工厂功能或类似的分享示例?

谢谢!

2 个答案:

答案 0 :(得分:4)

React.Component是一个简单的javascript函数,因为es6类是围绕它们的语法糖。所以我们可以使用我们喜欢的类似es5类的概念,例如我刚刚在这里借用了Backbone的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.state = {
            open: false
        };

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

new MyComponent();

这只是一个例子(并且未经测试),你可以做任何你喜欢的原型实现,因为它只是一个普通的功能。如果您搜索“es5继承”,您应该能够应用任何这些解决方案。

答案 1 :(得分: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>
}

在原型文件夹中,您可以写如下:

index.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> 
  )
}
相关问题