React躬行记(7)——表单

简介:  表单元素是一类拥有内部状态的元素,这些状态由其自身维护,通过这类元素可让用户与Web应用进行交互。HTML中的表单元素(例如<input>、<select>和<radio>等)在React中都有相应的组件实现,不仅如此,React还将它们分成两种:受控组件和非受控组件。

一、受控组件


  受控组件(Controlled Component)是指那些受React控制的表单元素,其状态(value、checked等属性)的变更由组件的state管理。对于不同的表单元素,其受控组件的形式会有所差异,接下来会讲解其中的三类。

1)文本框

  常用的单行文本框是一个type属性为“text”的<input>元素,它的值(即状态)由value属性控制。如果要监听文本框的状态变化,那么可以像下面这样操作。


class Text extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: "init"};
    this.handle = this.handle.bind(this);
  }
  handle(e) {
    this.setState({value: e.target.value.toUpperCase()});
  }
  render() {
    return <input value={this.state.value} onChange={this.handle} type="text" />;
  }
}


  上述代码实现了一个简单的功能,在改变文本框中的内容时,自动将其转换成大写字母。具体的更新过程可分为四步:

(1)在构造函数中初始化组件的state,并为文本框设置默认值。

(2)文本框注册onChange事件,监听其值的变化。

(3)在事件处理程序handle()中,通过e.target.value读取到输入的值,修改并同步(调用this.setState()方法)到组件的state中。

(4)组件重新渲染,完成文本框的内容更新。

  其他两类受控组件的更新过程与之类似,只是在细节处理上有所不同。

  观察上面的示例可以发现,文本框的数据来源于组件的state,通过onChange事件将输入的新数据再同步给组件的state,从而完成了一次双向数据绑定。

  React中的<textarea>元素(多行文本框),其使用类似于上面的<input>元素,也是通过value属性来获取值的,如下代码所示,省略了构造函数和事件处理程序。

class TextArea extends React.Component {
  render() {
    return <textarea value={this.state.value} onChange={this.handle} />;
  }
}

  而HTML中的<textarea>元素则会将值定义成子元素,并且包含结束标签,如下所示。

<textarea>init</textarea>

2)单选框和复选框

  单选框是一个type属性为“radio”的<input>元素,复选框是一个type属性为“checkbox”的<input>元素。与之前的文本框不同,React控制的不是它们的值,而是选中状态,即布尔属性checked。在下面的例子中,监听了每个单选框的checked属性。

class Radio extends React.Component {
  constructor(props) {
    super(props);
    this.state = { gender: "" };
    this.handle = this.handle.bind(this);
  }
  handle(e) {
    this.setState({
      gender: e.target.value
    });
  }
  render() {
    return (
      <>
        <input name="gender" value="1" onChange={this.handle} type="radio" 
          checked={this.state.gender == "1"}
        />男
        <input name="gender" value="2" onChange={this.handle} type="radio"
          checked={this.state.gender == "2"}
        />女
      </>
    );
  }
}


  复选框能选中多个项,其操作要比单选框繁琐许多。在下面的例子中,不但监听了每个复选框的checked属性,还将处于选中状态的值提取了出来,组成一个数组。


class Checkbox extends React.Component {
  constructor(props) {
    super(props);
    this.state = { colors: [] };        //保存复选框值的数组
    this.handle = this.handle.bind(this);
  }
  handle(e) {
    const { checked, value } = e.target;
    let { colors } = this.state;
    if (checked && colors.indexOf(value) == -1) {
      colors.push(value);            //已选中并且数组中未有该值,就在末尾插入
    } else {    
      colors = colors.filter(item => item != value);        //未选中,就将该值过滤掉
    }
    this.setState({ colors });
  }
  render() {
    return (
      <>
        <input name="colors" value="1" onChange={this.handle} type="checkbox"
          checked={this.state.colors.indexOf("1") >= 0}
        />红
        <input name="colors" value="2" onChange={this.handle} type="checkbox"
          checked={this.state.colors.indexOf("2") >= 0}
        />绿
        <input name="colors" value="3" onChange={this.handle} type="checkbox"
          checked={this.state.colors.indexOf("3") >= 0}
        />蓝
      </>
    );
  }
}


  虽然React处理单选框和复选框的方式要比在HTML中复杂一点,但是保证了组件的state是元素状态的唯一来源,进而让更新过程更加可靠和可控。

3)选择框

  在HTML中,<select>元素(选择框)会包含多个用来表示选项的<option>元素,而选中的项会被定义一个selected属性,如下代码所示,第二个<option>元素处于选中状态。

<select>
  <option value="1">strick</option>
  <option value="2" selected>freedom</option>
  <option value="3">jane</option>
</select>

  在React中,只需对<select>元素定义value属性就能决定当前的选中项,如下代码所示,这比用DOM的方式操作选项要简洁得多。


class Select extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: "" };
    this.handle = this.handle.bind(this);
  }
  handle(e) {
    this.setState({ value: e.target.value });
  }
  render() {
    return (
      <select value={this.state.value} onChange={this.handle}>
        <option value="1">strick</option>
        <option value="2">freedom</option>
        <option value="3">jane</option>
      </select>
    );
  }
}


  只要给<select>元素添加multiple属性并将其赋为true就能变为多选,如下代码所示,此时传给value属性的是一个数组。

class MulSelect extends React.Component {
  constructor(props) {
    super(props);
    this.state = { values: [] };
    this.handle = this.handle.bind(this);
  }
  handle(e) {
    const { options } = e.target;             //options是一个类数组对象
    const values = Object.keys(options)       //将options的索引组成一个数组
      .filter(i => options[i].selected)       //过滤出选中项
      .map(i => options[i].value);            //提取选中项组成新数组
    this.setState({ values });
  }
  render() {
    return (
      <select value={this.state.values} onChange={this.handle} multiple={true}>
        <option value="1">strick</option>
        <option value="2">freedom</option>
        <option value="3">jane</option>
      </select>
    );
  }
}


二、非受控组件


  非受控组件(Uncontrolled Component)的定义正好与受控组件的相左,其状态由自己管理,通常使用ref属性(第5篇中讲解过)获取表单元素的值。在下面的示例中,文本框在失去焦点时,能自动将其内容转换成大写字母。如果用受控组件的形式完成相同的功能,那么会较为繁琐。


class Text extends React.Component {
  constructor(props) {
    super(props);
    this.handle = this.handle.bind(this);
  }
  handle() {
    this.input.value = this.input.value.toUpperCase();
  }
  render() {
    return <input onBlur={this.handle} type="text" ref={ input => {this.input = input}}/>;
  }
}


  在render()方法中,首先为文本框注册onBlur事件,然后定义ref属性,其值是一个回调函数。当组件被挂载时,就会执行该回调函数,然后就能让this.input指向一个文本框,从而在事件处理程序handle()中就能通过this.input读取到文本框中的内容。

  在React中,有一个表单元素比较特殊,那就是上传按钮。它只有非受控组件的形式,因为其值只能由用户传入,不能被组件的state所控制。

1)默认值

  如果要指定非受控组件的默认值,那么可通过定义defaultValue或defaultChecked属性实现,前者适用于文本框、选择框等元素,后者适用于单选框和复选框。下面的示例分别给文本框和单选框设置了默认值,为了便于观察,只放出了关键代码。

class Text extends React.Component {
  render() {
    return <input type="text" defaultValue="init"/>;
  }
}
class Radio extends React.Component {
  render() {
    return (
      <>
        <input name="gender" value="1" type="radio"/>男
        <input name="gender" value="2" type="radio" defaultChecked={true}/>女
      </>
    );
  }
}



相关文章
|
2月前
|
移动开发 前端开发 JavaScript
React 表单与事件
10月更文挑战第10天
50 1
|
2月前
|
前端开发 JavaScript 数据安全/隐私保护
深入探索研究React表单
【10月更文挑战第6天】
91 57
|
21天前
|
存储 前端开发 JavaScript
React 表单输入组件 Input:常见问题、易错点及解决方案
本文介绍了在 React 中使用表单输入组件 `Input` 的基础概念,包括受控组件与非受控组件的区别及其优势。通过具体代码案例,详细探讨了创建受控组件、处理多个输入字段、输入验证和格式化的方法,并指出了常见易错点及避免方法,旨在提升表单的健壮性和用户体验。
33 4
|
1月前
|
前端开发 JavaScript
React 表单处理技巧
【10月更文挑战第24天】本文从初学者角度出发,详细介绍了 React 中表单处理的基本概念、常见问题及解决方案。涵盖受控组件与非受控组件的区别、状态更新、表单验证、多字段管理及高级技巧,通过代码示例帮助读者更好地理解和应用。
83 7
|
2月前
|
移动开发 JSON 数据可视化
精选八款包括可视化CMS,jquery可视化表单,vue可视化拖拉,react可视化源码
精选八款包括可视化CMS,jquery可视化表单,vue可视化拖拉,react可视化源码
60 0
|
3月前
|
人工智能 前端开发 JavaScript
react js 处理表单( form )的2个例子
react js 处理表单( form )的2个例子
|
4月前
|
容器 Kubernetes Docker
云原生JSF:在Kubernetes的星辰大海中,让JSF应用乘风破浪!
【8月更文挑战第31天】在本指南中,您将学会如何在Kubernetes上部署JavaServer Faces (JSF)应用,享受容器化带来的灵活性与可扩展性。文章详细介绍了从构建Docker镜像到配置Kubernetes部署全流程,涵盖Dockerfile编写、Kubernetes资源配置及应用验证。通过这些步骤,您的JSF应用将充分利用Kubernetes的优势,实现自动化管理和高效运行,开启Java Web开发的新篇章。
58 0
|
4月前
|
前端开发 JavaScript API
掌握React表单管理的高级技巧:探索Hooks和Context API如何协同工作以简化状态管理与组件通信
【8月更文挑战第31天】在React中管理复杂的表单状态曾是一大挑战,传统上我们可能会依赖如Redux等状态管理库。然而,React Hooks和Context API的引入提供了一种更简洁高效的解决方案。本文将详细介绍如何利用Hooks和Context API来优化React应用中的表单状态管理,通过自定义Hook `useForm` 和 `FormContext` 实现状态的轻松共享与更新,使代码更清晰且易于维护,为开发者带来更高效的开发体验。
49 0
|
4月前
|
前端开发 JavaScript 数据管理
React Formik入门:简化表单处理的神器——全面掌握Formik在React表单开发中的高效应用与实战技巧
【8月更文挑战第31天】在React应用中,表单处理常常因繁琐而令人头疼。Formik作为一个开源库,专为简化React表单设计,减少冗余代码并提升处理效率。本文介绍Formik的使用方法及其优势,通过示例展示如何安装配置并创建基本表单,帮助开发者轻松应对各种表单需求。
57 0
|
5月前
|
JavaScript 前端开发
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
188 1