反应js组件多态性

时间:2015-05-28 11:48:50

标签: reactjs

我有几个与验证功能相同的表格。 我想创建另一个具有相同行为的表单,除了验证函数。

我尝试使用mixins,但mixins不支持方法覆盖。

这个问题最好的方法是什么?

这是一个问题的示例:https://jsfiddle.net/69z2wepo/9150/

var FormMixin = {
    validate: function () {
        if (this.state.message !== '') {
            this.setState({status: 'ok'});
        } else {
            this.setState({status: 'error'});
        }
    },
    getInitialState: function () {
        return {
            message: 'Hello123!',
            status: ''
        };
    },
    handleChange: function (newValue) {
        this.setState({
            message: newValue
        });
    },
    valueLink: function() {
        return {
          value: this.state.message,
          requestChange: this.handleChange
        }     
    },
    render: function () {
        return (
         <div>
           <input type = "text" valueLink = {this.valueLink()} />
           <button onClick={this.validate} >Validate</button>
           <div>{this.state.status}</div>
         </div>
        );
    }
}

var Form = React.createClass({
    mixins: [FormMixin]
});

var FormEmpty = React.createClass({
    /*validate: function() { // How to override validation
      this.setState({status: 'ok'});
    },*/
    mixins: [FormMixin]
});

var Hello = React.createClass({
    render: function() {
        return (<div>
            <Form />
            <Form />
            <Form />
            <FormEmpty />
        </div>);
    }
});

React.render(<Hello />, document.getElementById('container'));

3 个答案:

答案 0 :(得分:2)

Mixins可能不是最好的方法,它们不适合React 0.13 +中提供的真正的JavaScript class模型。

一种简单的替代方法是使用从Form到父组件的事件/回调,它可以提供自定义验证(jsFiddle here)。例如:

var Form = React.createClass({
    propTypes: {
        validationOverride: React.PropTypes.func
    },

    validate: function () {
        if (this.props.validationOverride) {
            this.setState({status: this.props.validationOverride() });
            return;
        } 
        if (this.state.message !== '') {
            this.setState({status: 'ok'});
        } else {
        this.setState({status: 'error'});
        }
    },
    getInitialState: function () {
        return {
            message: 'Hello123!',
            status: ''
        };
    },
    handleChange: function (newValue) {
        this.setState({
            message: newValue
        });
    },
    valueLink: function() {
        return {
          value: this.state.message,
          requestChange: this.handleChange
        }     
    },
    render: function () {
        return (
         <div>
           <input type = "text" valueLink = {this.valueLink()} />
           <button onClick={this.validate} >Validate</button>
           <div>{this.state.status}</div>
         </div>
        );
    }
});

var FormEmpty = React.createClass({
    validate: function() {
        // you could pass in values to this function
        return "NOT OK!";
    },
    render: function() {
        return <Form validationOverride={ this.validate } />;    
    }
});

虽然我遗漏了一些细节(因为它不清楚验证的效果如何),但您可以看到我是如何创建第二个名为FormEmpty的类包含单个孩子Form。它将函数作为名为validationOverride的回调传递。验证需要运行时Form调用(如果已设置)。如果未设置,则应用标准验证逻辑。

当然,您可以选择对此进行结构化,以便有一个从未进行过验证的基类,并且始终需要通过验证功能。通过这种方式,您始终需要执行父级和基本表单的组合来执行验证(这将是一种非常常见的React模式)。

答案 1 :(得分:0)

请看一下

https://github.com/gcanti/tcomb-form

https://github.com/gcanti/tcomb-validation

如果您使用简单的表单和验证,这非常方便。

答案 2 :(得分:-1)

您可以创建一个以验证函数作为参数的mixin工厂。

function FormMixin(validate) {
    return {
        validate: validate,
        /* ... */
    };
}

var Form = React.createClass({
    mixins: [FormMixin(validateMessage)]
});

请注意,mixins无法覆盖render。您可能最好创建一个简单的Form组件,该组件接收validate道具并在其他表单组件中重复使用。