表单

作者: 莫铭 | 来源:发表于2017-04-28 00:15 被阅读18次

在React中,HTML表单元素与其他的DOM元素有些不同,因为表单元素会自己保持一些内部状态。举例来说,下面这个简单HTML中的表单,只接收一个名字:

<form>
  <label>
    Name:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="Submit" />
</form>

HTML表单有个默认行为,当用户提交表单时,会打开一个新的页面。在React中,这个行为默认开启。但是大多数情况下,最方便的还是有个JavaScript函数来处理表单的提交,直接访问用户输入到表单的数据。实现这个的标准做法:使用一个称为“受控组件”的技术。

受控组件

在HTML中,诸如<input><textarea><select>的表单元素一般都维护他们自身的状态,根据用户的输入更新这个状态。在React中,可变状态一般保存在组件的状态属性中,只通过setState进行更新。
我们可以通过让React的状态成为"真相的唯一来源"来组合这两者。这样,在用户一系列输入后,渲染表单的React组件会去控制表单中会发生什么。
由React控制input表单元素的值,这就是所谓的“受控组件”:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

在CodePen上试一试
由于我们设置了表单元素上的value属性,显示出的值始终是this.state.value,这样React状态就成为了真相的来源。由于每次敲击键盘都会运行handleChange来更新React状态,显示的值就像是由于用户输入而更新的。
受控组件中,每个状态变化都会有个关联处理函数。这样就可以直接修改和验证用户的输入。假如我们想强制名字全部用大写字母,我们可以将handleChange写成:

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

textarea标签

HTML中,<textarea>元素通过他的孩子定义自己的文本:

<textarea>
  Hello there, this is some text in a text area
</textarea>

而在React中,<textarea>使用属性value来代替。这样的话,一个使用<textarea>的表单就可以写成单行的形式:

class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 'Please write an essay about your favorite DOM element.'
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('An essay was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

注意this.state.value在构造函数中被初始化了,所以文本区一开始就有文本。

select标签

HTML中,<select>创建下拉列表。比如,下面这段HTML创建了一个调味料的下拉列表:

<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>

注意,由于selected属性,Coconut是初始选项。而在React中,使用根节点select标签的value属性来代替selected属性。这在受控组件中更为方便,因为你仅需在一个地方更新它。举个例子:

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('Your favorite flavor is: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Pick your favorite La Croix flavor:
          <select value={this.state.value} onChange={this.handleChange}>
            <option value="grapefruit">Grapefruit</option>
            <option value="lime">Lime</option>
            <option value="coconut">Coconut</option>
            <option value="mango">Mango</option>
          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

在CodePen上试一试
总的来说,这使得<input type="text">,<textarea>, 和<select>非常类似 - 他们接受一个value属性,使用这个属性就能实现一个受控组件。

处理多个输入

当你需要处理多个受控的input元素,你可以为每个元素添加一个name属性,然后让处理函数根据event.target.name的值选择怎么去做。
举例来说:

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

在CodePen上试一试
注意我们是用ES6的计算属性名语法,根据给定的输入名来更新状态键:

this.setState({
  [name]: value
});

这和下面的ES5代码等价:

var partialState = {};
partialState[name] = value;
this.setState(partialState);

此外,由于setState()会自动合并部分状态到现有的状态中,我们调用时只需传入改变的部分即可。

受控组件的替代方案

使用受控组件有时可能很繁琐,因为你需要为数据变化的每种可能编写一个事件处理器,并通过React组件传输所有的输入状态。当你需要将已有代码转到React,或将React应用与非React库整合在一起时,这会变得特别烦人。在这些情况中,你可能需要审视下非受控组件,一个实现输入表单的替代技术。

相关文章

  • bootstrap之form表单

    表单布局 垂直表单(默认) 内联表单 水平表单 垂直表单或基本表单(display:block;) 创建基本表单的...

  • 【读书笔记+思考】移动设备表单设计

    在移动界面中,常见的表单模式有:登录表单;注册表单;核对表单;计算表单;搜索表单;多步骤表单;长表单等 登录表单:...

  • bootstrap表单

    表单布局 垂直表单(默认) 内联表单 水平表单 垂直表单或基本表单 基本的表单结构是 Bootstrap 自带的,...

  • bootstrap 表单布局的三种方式

    三种 垂直表单(默认) 内联表单 水平表单 垂直表单 效果 内联表单 效果 水平表单 效果 参考:https://...

  • 表单相关总结

    表单?表单作用:收集用户信息。表单组成:表单域、表单控件、提示信息。 表单域常用属性 常用属性: name=...

  • 网页设计:HTML表单标签

    表单包含三个基本组成部分:表单标签、表单域、表单按钮。 1,表单标签 HTML 表单用于收集用户输入,表单使用 ...

  • 2019-04-09 表单(5)

    表单布局Bootstrap 提供了下列类型的表单布局: 垂直表单(默认) 内联表单 水平表单 1.垂直或基本表单 ...

  • 动态表单实现

    angular动态表单 地址: angular表单 vue动态表单 地址: vue表单

  • bootstrap表单

    垂直表单(默认) 内联表单 水平表单 垂直表单 也称基本表单基本的表单结构是 bootstrap 自带的创建基本表...

  • 前端视频-day3(1)

    表单 表单不是表格,表单的核心是数据。 表单标签的构成和形式: 表单项 下面是我写的一个简单的注册表单 注意:表单...

网友评论

    本文标题:表单

    本文链接:https://www.haomeiwen.com/subject/wlynzttx.html