React - 如何使表单与其子代进行通信(表单输入)

时间:2015-09-06 05:20:06

标签: reactjs

我的概念是制作一个包含Form的{​​{1}},如果未填写任何必需的FormElements,则其所有者FormElements会知道该信息。因为我是React的新手,所以我无法理解如何让他们进行沟通。这是我到目前为止的一点:

Form

然后使用表格:

Form = React.createClass({
  getInitialState() {
    return {
      validated: false
    }
  },

  render() {
    return (
      <form id={this.props.id}>
        {this.props.children}
      </form>
    )
  },

  componentDidMount() {
    React.Children.forEach(this.props.children, function (el) {
      if (el.props.type === 'submit') {
        console.log(el);
        $(el).prop('disabled', true);
      }
    });
  }
});

FormElement = React.createClass({
  propTypes: {
    id: React.PropTypes.string.isRequired,
    label: React.PropTypes.string.isRequired,
    type: React.PropTypes.string,
    required: React.PropTypes.bool
  },

  getDefaultProps() {
    return {
      type: 'text',
      required: false
    }
  },

  getInitialState() {
    return {
      focused: false,
      filled: false,
      touched: false
    }
  },

  handleFocus(focused) {
    this.setState({focused, touched: true});
  },

  handleKeyUp(event) {
    this.setState({filled: event.target.value.length > 0});
  },

  render() {
    let formElement;

    if (_.contains(['text', 'email', 'password'], this.props.type)) {
      formElement = (
        <div className="form-group">
          <label className={this.state.focused || this.state.filled ? "focused" : ""}
                 htmlFor={this.props.id}>{this.props.label}</label>
          <input type={this.props.type}
                 className="form-control"
                 id={this.props.id}
                 onFocus={this.handleFocus.bind(null, true)}
                 onBlur={this.handleFocus.bind(null, false)}
                 onKeyUp={this.handleKeyUp} />
        </div>
      );
    } else if (this.props.type === 'submit') {
      formElement = (
        <button type="submit"
                ref="submitButton"
                className="btn btn-primary">{this.props.label}</button>
      );
    }

    return formElement;
  }
});

您可以在 <Form id="login-form"> <FormElement id="email" label="Email Address" type="email" required={true} /> <FormElement id="password" label="Password" type="password" required={true} /> <FormElement id="login-button" label="Log In" type="submit" /> </Form> 中看到React.Children.forEach循环,我正在尝试查看提交按钮是否存在,并默认禁用它,但我不知道如何操作该循环中的对象。 jQuery调用什么都不做。这也可能是完全错误的做法。

代码尚未完成(就验证而言)。我们的想法是,如果需要FormFormElementtouched === true,那么父filled === false将以某种方式知道该状态并保持提交按钮被禁用。

2 个答案:

答案 0 :(得分:1)

我认为你可能试图在表单元素中加入过多的逻辑,并且在使用React时,你不应该尝试触及DOM,因为你在循环中使用了一些jQuery操作。

我这样做的方式,表单会有一些与之关联的状态,即所有字段的内容。 render会将这些值传递给FormElement s,这会将它们传递给inputFormElement会向委托给onChange的{​​{1}}提供inputonChange将由Form提供,disabled将处理此更改并更新其状态。这为您提供了表单的基本功能。

由于表单现在知道当前填写的数据,因此可以直接推断是否应该启用提交按钮。然后,它可以将FormElement属性传递给render函数中的FormElementinput可以将其传递给<script src="https://fb.me/react-0.13.3.min.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <div id="application"></div> <script type="text/jsx"> var Form = React.createClass({ getInitialState: function getInitialState() { return { firstName: "", lastName: "" }; }, render: function render() { return <form> <FormElement label="First name" value={this.state.firstName} onChange={this.firstNameChanged} /> <FormElement label="Last name" value={this.state.lastName} onChange={this.lastNameChanged} /> <SubmitButton enabled={!!this.state.firstName.trim() && !!this.state.lastName.trim()} /> </form>; }, firstNameChanged: function(newFirstName) { this.setState({firstName: newFirstName}); }, lastNameChanged: function(newLastName) { this.setState({lastName: newLastName}); } }); var FormElement = React.createClass({ render: function render() { return <p><label>{this.props.label}: <input type="text" value={this.value} onChange={this.changed} /></label></p>; }, changed: function changed(e) { if(this.props.onChange) { this.props.onChange(e.target.value); } } }); var SubmitButton = React.createClass({ render: function render() { return <p><input type="submit" value="Submit" disabled={!this.props.enabled} /></p>; } }); React.render(<Form />, document.getElementById("application")); </script>

简化示例:

Form

在评论中,您说您希望LoginForm不知道任何特定字段。好吧,你也可以这样做:将数据存储在你的FormElement或者你拥有的内容中,然后再让数据流下来并提供一种向父母提供回调的方法,例如: (这里放弃<script src="https://fb.me/react-0.13.3.min.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <div id="application"></div> <script type="text/jsx"> var NameForm = React.createClass({ getInitialState: function getInitialState() { return { firstName: "", lastName: "" }; }, render: function render() { return <Form fields={this.getFields()} onFieldChange={this.fieldChanged} canSubmit={this.canSubmit()} />; }, getFields: function getFields() { return [ {id: "firstName", label: "First name", value: this.state.firstName}, {id: "lastName", label: "Last name", value: this.state.lastName} ]; }, fieldChanged: function fieldChanged(which, newValue) { if(which === "firstName") { this.setState({firstName: newValue}); }else if(which === "lastName") { this.setState({lastName: newValue}); } }, canSubmit: function canSubmit() { return !!this.state.firstName && !!this.state.lastName; } }); var Form = React.createClass({ render: function render() { return <form> {this.props.fields.map(function(field) { return <p key={field.id}><label>{field.label}: <input type="text" value={field.value} onChange={this.fieldChanged.bind(null, field.id)} /></label></p>; }.bind(this))} <input type="submit" value="Submit" disabled={!this.props.canSubmit} /> </form>; }, fieldChanged: function(which, e) { if(this.props.onFieldChange) { this.props.onFieldChange(which, e.target.value); } } }); React.render(<NameForm />, document.getElementById("application")); </script>,因为这些片段越来越长,我不想贬低这一点):

import turtle


centerX = float(input("Enter the center x cordinates of the rectangle: "))
centerY = float(input("Enter the center y cordinates of the rectangle: "))
width = float(input("enter, width: "))
height = float(input("enter, height: "))


turtle.showturtle()

turtle.penup()
turtle.goto(centerX,centerY)
turtle.pendown()
turtle.goto(-width/2,centerY)
turtle.goto(-width/2,height/2)
turtle.goto(width,height/2)
turtle.goto(width,-height)
turtle.goto(-width,-height)
turtle.goto(-width,height/2)

答案 1 :(得分:0)

当谈到React元素之间的通信时,我终于来到Flux,因为它是为此目的而设计的。基本上,您创建一个包含验证用户输入的所有逻辑的单个状态机(存储),任何可能还有配置所需内容的方法/需要哪些字段。 Form的每个领域/孩子都在商店注册,告诉它“嘿,我在这里,我提供这个/那个信息”。最后在提交时,商店检查所有已注册/必填字段是否报告了有效的用户输入