HTML表单元素和 React里的其他DOM元素有些不同,因为它们会保留一些内部的状态。举个例子,这个普通的表单接受唯一的name值:

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

这个表单具有默认的表单行为,当用户提交表单就会跳转到新页面。如果你想要在React里实现此行为,它自然而然就会实现。但是在大多数情况下,定义一个控制表单提交并且有能力控制用户输入的表单数据的js函数会更方便。实现这个的标准方法是一种叫“受控组件”的技术。

受控组件

在HTML里,<input>,<textarea>和<select>这类元素通常包含它们自己的状态并且会基于用户输入而更新状态。在React中,易变的状态通常会保存在组件的state属性里,并且只能使用setState()来更新。

我们可以联合两种状态通过设置React state为“单一数据源”。然后React组件会渲染表单也会控制随后用户的输入。这样子的表单元素输入的值被React控制的方法叫做“受控组件”。

举个例子,如果我们想要让上一个例子当提交的时候记录name值,我们可以把表单写成一个受控组件:

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属性被设置在表单元素上,被显示的value值就永远会是this.state.value,使得React的state是单一数据源。当每次修改表单值的时候handleChange就会更新React的state,只要输入改变显示的值就会更新。

通过控制组件,每一个state的变化都会有一个联合的处理函数。这让它可以明确的修改或者确认用户输入。举个例子,如果我们想要强制name值都用大写字母来写,那么我们应该像这样写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>能够像这样写,跟使用单行input的表单类似:

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>

注意Coconut选项是初始就被选择的,因为selected属性。在React里,我们不使用selected属性,而是在select标签里使用value属性。在控制组件里这样更加方便因为你只需要在一个地方更新默认选择项即可。举个例子:

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属性来完成一个控制组件。

file input 标签

在HTML当中,<input type="file"> 允许用户从他们的存储设备中选择一个或多个文件以提交表单的方式上传到服务器上, 或者通过 Javascript 的 File API 对文件进行操作 。

由于该标签的 value 属性是只读的, 所以它是 React 中的一个非受控组件。我们会把它和其他非受控组件一起在后面的章节进行详细的介绍。

处理多个输入

当你需要处理多个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的“计算出的属性名”语法来更新state key通过对应的input name:

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

ES5语法这样写:

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

同样,只要setState()自动的将部分state合并到了当前的state,我们只需要调用它来更新被改变的部分。

控制组件的可选方案

有时使用受控组件可能很繁琐,因为您要为数据可能发生变化的每一种方式都编写一个事件处理程序,并通过一个组件来管理全部的状态。当您将预先存在的代码库转换为React或将React应用程序与非React库集成时,这可能变得特别烦人。在以上情况下,你或许应该看看非受控组件,这是一种表单的替代技术。

React文档(十)表单的更多相关文章

  1. 【JEECG技术文档】表单配置-树形表单

    表单配置支持树型表单了,具体效果如下图: 配置说明: 1.是否树:选择是. 2.树形表单父Id:表的自关联外键. 3.树形表单列表:显示树形图标的列,如上图中为[组织机构名称]. 4.默认值:最外层数 ...

  2. React文档(十三)思考React

    在我们的看来,React是使用js创建大型快速网站应用的首要方法.它在Facebook和Instagram的使用已经为我们展现了它自己. React的一个很好的地方就在于当你创建应用的时候它使你思考如 ...

  3. React文档(二十四)高阶组件

    高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...

  4. 文档驱动 —— 表单组件(五):基于Ant Design Vue 的表单控件的demo,再也不需要写代码了。

    源码 https://github.com/naturefwvue/nf-vue3-ant 特点 只需要更改meta,既可以切换表单 可以统一修改样式,统一升级,以最小的代价,应对UI的升级.切换,应 ...

  5. 文档驱动 —— 表单组件(六):基于AntDV的Form表单的封装,目标还是不写代码

    开源代码 https://github.com/naturefwvue/nf-vue3-ant 也不知道大家是怎么写代码的,这里全当抛砖引玉 为何封装? AntDV非常强大,效果也非常漂亮,功能强大, ...

  6. React文档(一)安装

    React是一个灵活的可以用于各种不同项目的框架,你可以用它来写新应用,你也可以逐步将它引进已有的代码库而不用重写整个项目. 试用React 如果你想玩一玩React,那么就去CodePen上试一试. ...

  7. Android根据word模板文档将表单数据生成word文档的方案整理

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 尝试的方案包括以下几种: freemarker 只能在java项目上运行,无法在Android项目上运行: 参考资料:<Fre ...

  8. react文档demo实现输入展示搜索结果列表

    文档页面地址:https://doc.react-china.org/docs/thinking-in-react.html 该文档只给了具体实现思路,下面是我实现的代码. 初学react,如果有写的 ...

  9. React文档(十七)非受控组件

    大多数情况下,我们建议使用受控组件(也就是用React的state来控制表单元素的value值)来实现表单.在一个受控组件里,表单数据被React组件处理.另一种方案就是非控制组件,这样的话表单数据就 ...

随机推荐

  1. Linux服务器上搭建web项目环境

    一.下载并安装jdk 去官网下载linux系统上jdk的安装包jdk-8u181-linux-x64.tar.gz,在Linux的/usr目录下新建文件夹java,可以使用命令:cd /usr    ...

  2. qmp的简单使用

    QMP是一种基于JSON格式的传输协议,可使用QMP与一个QEMU虚拟机实例进行交互,例如查询虚拟机的相关状态等,以下就QMP的使用进行简单介绍. 可以通过libvirt向一个运行的虚拟机发送qmp命 ...

  3. 15.4-uC/OS-III资源管理(二值信号量)

    互斥信号量是 uC/OS 操作系统的一个内核对象, 与多值信号量非常相似,但它是二值的,只能是 0 或 1,所以也叫二值信号量, 主要用于保护资源. 1.如果想要使用互斥信号量,就必须事先使能互斥信号 ...

  4. python之以字符串形式导入模块

    示例 调用方法 class CorsMiddleware: def process(self): print('from auth.cors.CorsMiddleware.process') cors ...

  5. vs安装问题

    1 首先windows update异常,导致vs2015的一个安装不上,先试着修一下: https://support.microsoft.com/zh-cn/help/2629484 如果提示:“ ...

  6. VUE—打印(原生态网页打印)

    //打印触发的方法 print(e){ let subOutputRankPrin = document.getElementById('printcode'); var options = { fo ...

  7. .net core 配置

    .net core 配置包括很多种 例如内存变量.命令行参数.环境变量以及物理文件配置和自定义配置 物理文件配置主要有三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonConfi ...

  8. Java作业(一)

    再此次的Java考试中发现自己的不足,无法套用HTML模板进行编程,说实话拿到的第一刻自己有些懵,不知道怎么去操作, 后来通过查询操作了一些,但是整个人还是懵懵的,不知道下一步怎么办,怎么去连接后台和 ...

  9. SpringBoot项目启动时链接数据库很慢

    SpringBoot项目启动时链接数据库很慢 springboot项目在启动时候,如下图所示,链接数据库很慢 解决方法:在mysql 的配置文件中 配置 skip-name-resolve

  10. bootstrap-wysiwyg这个坑

    但是用wysiwyg也是费了我不少的精力,特别是在图片上传上,下面做一些总结. 1.引入文件 wysiwyg号称只有5kb,但是实际上是将其他的依赖文件在cdn上用外链链接进来了,有以下几个文件: c ...