React中,表单元素和其他元素的工作有些差异 ,因为表单元素天生包括一些内置状态。举例来说,这个原生HTML表单接受一个name:

  1. <form>
  2. <label>
  3. Name:
  4. <input type="text" name="name" />
  5. </label>
  6. <input type="submit" value="Submit" />
  7. </form>

该表单具有原生HTML行为:当用户点击提交,浏览修的页面。你希望React中也有这样的行为也是奏效的。但是更普遍的场景中,使用一个JavaScript函数处理表单提交,并且访问用户在表单中输入的数据是很方便的。标准的方式来完成上述功能使用技术叫“控制组件”(Controlled Component)。

控制组件

HTML中,像,这样的元素,通常维持他们自己的状态并根据用户输入更新。在React中,可变的状态通常在组件的state中体现并且只能由setState()更新。

将React状态变成“真理的唯一源头”,我们就能将这两点结合起来。接着,渲染了表单的React组件也能在用户随之而来的输入中控制着表单。一个由React控制着的输入表单元素在这种方式下就叫“控制组件”。

举例,如果我们想将先前的例子变成点击提交后输出name,我们可以把表单写成像控制组件那样:

  1. class NameForm extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {value: ''};
  5. this.handleChange = this.handleChange.bind(this);
  6. this.handleSubmit = this.handleSubmit.bind(this);
  7. }
  8. handleChange(event) {
  9. this.setState({value: event.target.value});
  10. }
  11. handleSubmit(event) {
  12. alert('A name was submitted: ' + this.state.value);
  13. event.preventDefault();
  14. }
  15. render() {
  16. return (
  17. <form onSubmit={this.handleSubmit}>
  18. <label>
  19. Name:
  20. <input type="text" value={this.state.value} onChange={this.handleChange} />
  21. </label>
  22. <input type="submit" value="Submit" />
  23. </form>
  24. );
  25. }
  26. }

既然value属性是我们表单自己设置的,那显示的值永远是this.state.value,反映着‘真理的源头’。由于在每一次键盘输入后都会调用handleChange来更新state状态,显示在界面的数值就会根据用户输入更新。

使用控制组件,每一个可变状态将会关联一个处理函数。这使得它可以直接修改或者验证用户输入。举例来说,假如我们想强行的把name变成大写字母,我们可以再handleChange中这样写:

  1. handleChange(event) {
  2. this.setState({value: event.target.value.toUpperCase()});
  3. }

标签:textarea

在HTML中,textarea标签通过其子元素定义它的文本。

  1. <textarea>
  2. Hello there, this is some text in a text area
  3. </textarea>

在React中,textarea标签使用value属性代替。用这样的方式,使用

  1. class EssayForm extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. value: 'Please write an essay about your favorite DOM element.'
  6. };
  7. this.handleChange = this.handleChange.bind(this);
  8. this.handleSubmit = this.handleSubmit.bind(this);
  9. }
  10. handleChange(event) {
  11. this.setState({value: event.target.value});
  12. }
  13. handleSubmit(event) {
  14. alert('An essay was submitted: ' + this.state.value);
  15. event.preventDefault();
  16. }
  17. render() {
  18. return (
  19. <form onSubmit={this.handleSubmit}>
  20. <label>
  21. Name:
  22. <textarea value={this.state.value} onChange={this.handleChange} />
  23. </label>
  24. <input type="submit" value="Submit" />
  25. </form>
  26. );
  27. }
  28. }

注意我们在构造器中初始化this.state.value,这样textarea一开始就有文字在里面。

标签:select

HTML中, 标签生成下拉表单,举例,下面的HTML生成喜好的列表:

  1. <select>
  2. <option value="grapefruit">Grapefruit</option>
  3. <option value="lime">Lime</option>
  4. <option selected value="coconut">Coconut</option>
  5. <option value="mango">Mango</option>
  6. </select>

注意Coconut选项是默认初始选择的,因为设置了selected属性。React中,不用selected属性,用select根标签中的value属性。这样对于控制组件来说更方便因为你只需在一处更新,就像这样:

  1. class FlavorForm extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {value: 'coconut'};
  5. this.handleChange = this.handleChange.bind(this);
  6. this.handleSubmit = this.handleSubmit.bind(this);
  7. }
  8. handleChange(event) {
  9. this.setState({value: event.target.value});
  10. }
  11. handleSubmit(event) {
  12. alert('Your favorite flavor is: ' + this.state.value);
  13. event.preventDefault();
  14. }
  15. render() {
  16. return (
  17. <form onSubmit={this.handleSubmit}>
  18. <label>
  19. Pick your favorite La Croix flavor:
  20. <select value={this.state.value} onChange={this.handleChange}>
  21. <option value="grapefruit">Grapefruit</option>
  22. <option value="lime">Lime</option>
  23. <option value="coconut">Coconut</option>
  24. <option value="mango">Mango</option>
  25. </select>
  26. </label>
  27. <input type="submit" value="Submit" />
  28. </form>
  29. );
  30. }
  31. }

总之,这样, 工作起来就很相似— 他们都接受value属性,通过value可以实现控制组件。

注意: 你也能在value属性中传递一个数组,这样做能实现多选项选中: