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

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

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

受控组件

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

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

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

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

在CodePen里试一试

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

通过控制组件,每一个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属性来代替文本值。像这样,一个表单使用一个<textarea>能够像这样写,跟使用单行input的表单类似:

  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.  
  8. this.handleChange = this.handleChange.bind(this);
  9. this.handleSubmit = this.handleSubmit.bind(this);
  10. }
  11.  
  12. handleChange(event) {
  13. this.setState({value: event.target.value});
  14. }
  15.  
  16. handleSubmit(event) {
  17. alert('An essay was submitted: ' + this.state.value);
  18. event.preventDefault();
  19. }
  20.  
  21. render() {
  22. return (
  23. <form onSubmit={this.handleSubmit}>
  24. <label>
  25. Name:
  26. <textarea value={this.state.value} onChange={this.handleChange} />
  27. </label>
  28. <input type="submit" value="Submit" />
  29. </form>
  30. );
  31. }
  32. }

注意this.state.value在构造函数里被初始化,因此文本区域一开始就会有文本值。

select标签

在HTML里,<select>创建了一个下拉列表。举个例子,这段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.  
  6. this.handleChange = this.handleChange.bind(this);
  7. this.handleSubmit = this.handleSubmit.bind(this);
  8. }
  9.  
  10. handleChange(event) {
  11. this.setState({value: event.target.value});
  12. }
  13.  
  14. handleSubmit(event) {
  15. alert('Your favorite flavor is: ' + this.state.value);
  16. event.preventDefault();
  17. }
  18.  
  19. render() {
  20. return (
  21. <form onSubmit={this.handleSubmit}>
  22. <label>
  23. Pick your favorite La Croix flavor:
  24. <select value={this.state.value} onChange={this.handleChange}>
  25. <option value="grapefruit">Grapefruit</option>
  26. <option value="lime">Lime</option>
  27. <option value="coconut">Coconut</option>
  28. <option value="mango">Mango</option>
  29. </select>
  30. </label>
  31. <input type="submit" value="Submit" />
  32. </form>
  33. );
  34. }
  35. }

在CodePen里试一试

总得来说,<input type="text">,<textarea>和<select>都类似,他们都接受一个value属性来完成一个控制组件。

file input 标签

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

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

处理多个输入

当你需要处理多个input表单元素的时候,你可以给每一个元素添加一个name属性并且让处理函数选择基于event.target.name的值。

举个例子:

  1. class Reservation extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. isGoing: true,
  6. numberOfGuests: 2
  7. };
  8.  
  9. this.handleInputChange = this.handleInputChange.bind(this);
  10. }
  11.  
  12. handleInputChange(event) {
  13. const target = event.target;
  14. const value = target.type === 'checkbox' ? target.checked : target.value;
  15. const name = target.name;
  16.  
  17. this.setState({
  18. [name]: value
  19. });
  20. }
  21.  
  22. render() {
  23. return (
  24. <form>
  25. <label>
  26. Is going:
  27. <input
  28. name="isGoing"
  29. type="checkbox"
  30. checked={this.state.isGoing}
  31. onChange={this.handleInputChange} />
  32. </label>
  33. <br />
  34. <label>
  35. Number of guests:
  36. <input
  37. name="numberOfGuests"
  38. type="number"
  39. value={this.state.numberOfGuests}
  40. onChange={this.handleInputChange} />
  41. </label>
  42. </form>
  43. );
  44. }
  45. }

在CodePen里试一试

注意我们是怎样使用ES6的“计算出的属性名”语法来更新state key通过对应的input name:

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

ES5语法这样写:

  1. var partialState = {};
  2. partialState[name] = value;
  3. 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. Spring之IOC注入

    注入 spring依赖注入 set方法: <property name="属性名" values ="值">--ref="对象名" ...

  2. grep匹配字符串

    基本正则表达式 元数据 意义和范例 ^word 搜寻以word开头的行. 例如:搜寻以#开头的脚本注释行 grep –n ‘^#’ regular.txt word$ 搜寻以word结束的行 例如,搜 ...

  3. Spring Boot 基于Spring Initializer 的快速构建 day02

    一.基于Spring Initializr 快速构建Spring Boot项目(快速) 备注:需要联网 这是使用Intellij Idea快速构建可以为我们省去大量的pom.xml配置时间,简单操作, ...

  4. 016-并发编程-java.util.concurrent.locks之-Lock及ReentrantLock

    一.概述 重入锁ReentrantLock,就是支持重进入的锁 ,它表示该锁能够支持一个线程对资源的重复加锁.支持公平性与非公平性选择,默认为非公平. 以下梳理ReentrantLock.作为依赖于A ...

  5. Python 总结

    python3.7下载地址 Python安装pip 1.首先检查linux有没有安装python-pip包,直接执行 yum install python-pip 2.没有python-pip包就执行 ...

  6. [LeetCode] 62. Unique Paths_ Medium tag: Dynamic Programming

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  7. Centos使用natapp教程

    官网:https://natapp.cn/ 首先在Natapp站注册账号 点击注册 登录后,点击左边 购买隧道,免费/付费均可 根据需要选择隧道协议,这里以web演示,购买隧道 在 https://n ...

  8. JAVA微信公众号网页开发 —— 接收微信服务器发送的消息

    WeixinMessage.java package com.test; import java.io.Serializable; /** * This is an object that conta ...

  9. git----------如何创建develop分支和工作流,以及如何将develop上的代码合并到master分支上

    1.点击sourceTree 右上角的git工作流,或弹出一个弹出框,无需修改任何东西直接点击确认就可以创建develop. . 2.这里有两个分支了,当前高亮的就是你当前处在的分支.此时develo ...

  10. CentOS 7 MariaDB-MHA

    关于MHA    MHA(Master High Availability)是一款开源的mysql高可用程序,目前在mysql高可用方面是一个相对成熟的解决方案.MHA 搭建的前提是MySQL集群中已 ...