react自动触发表单提交_玩转 React 表单 —— 受控组件详解

本文涵盖以下受控组件:文本输入框

数字输入框

单选框

复选框

文本域

下拉选择框

同时也包含:表单数据的清除和重置

表单数据的提交

表单校验点击这里直接查看示例代码。 查看示例。 请在运行示例时打开浏览器的控制台。

介绍

在学习 React.js 时我遇到了一个问题,那就是很难找到受控组件的真实示例。受控文本输入框的例子倒是很丰富,但复选框、单选框、下拉选择框的例子却不尽人意。

本文列举了真实的受控表单组件示例,要是我在学习 React 的时候早点发现这些示例就好了。除了日期和时间输入框需要另开篇幅详细讨论,文中列举了所有的表单元素。

有时候,为了减少开发时间,有时候人们很容易为了一些东西(譬如表单元素)引入一个库。而对于表单,我发现当需要添加自定义行为或表单校验时,使用库会让事情变得更复杂。不过一旦掌握合适的 React 模式,你会发现构建表单组件并非难事,并且有些东西完全可以自己动手,丰衣足食。请把本文的示例代码当作你创建表单组件的起点或灵感之源。

除了提供单独的组件代码,我还将这些组件放进表单中,方便你理解子组件如何更新父组件 state ,以及接下来父组件如何通过 props(单向数据流)更新子组件。

注意:本表单示例由很赞的create-react-app构建配置生成,如果你还没有安装该构建配置,我强烈推荐你安装一下(npm install -g create-react-app)。目前这是搭建 React 应用最简单的方式。

什么是受控组件?

受控组件有两个特点:受控组件提供方法,让我们在每次 onChange 事件发生时控制它们的数据,而不是一次性地获取表单数据(例如用户点提交按钮时)。“被控制“ 的表单数据保存在 state 中(在本文示例中,是父组件或容器组件的 state)。 (译注:这里作者的意思是通过受控组件, 可以跟踪用户操作表单时的数据,从而更新容器组件的 state ,再单向渲染表单元素 UI。如果不使用受控组件,在用户实时操作表单时,比如在输入框输入文本时,不会同步到容器组件的 state,虽然能同步输入框本身的 value,但与容器组件的 state 无关,因此容器组件只能在某一时间,比如提表单时一次性地拿到(通过 refs 或者选择器)表单数据,而难以跟踪)

受控组件的展示数据是其父组件通过 props 传递下来的。

这个单向循环 —— (数据)从(1)子组件输入到(2)父组件的 state,接着(3)通过 props 回到子组件,就是 React.js 应用架构中单向数据流的含义。

表单结构

我们的顶级组件叫做App,这是它的代码:

import React, { Component } from 'react';

import '../node_modules/spectre.css/dist/spectre.min.css';

import './styles.css';

import FormContainer from './containers/FormContainer';

class App extends Component {

render() {

return (

React.js Controlled Form Components

);

}

}

export default App;

App只负责渲染index.html页面。整个App组件最有趣的部分是 13 行,FormContainer组件。

插曲: 容器(智能)组件 VS 普通(木偶)组件

是时候提及一下容器(智能)组件和普通(木偶)组件了。容器组件包含业务逻辑,它会发起数据请求或进行其他业务操作。普通组件则从它的父(容器)组件接收数据。木偶组件有可能触发更新 state (译注:容器组件的 state)这类逻辑行为,但它仅通过从父(容器)组件传入的方法来达到该目的。

注意: 虽然在我们的表单应用里父组件就是容器组件,但我要强调,并非所有的父组件都是容器组件。木偶组件嵌套木偶组件也是可以的。

回到应用结构

FormContainer组件包含了表单元素组件,它在生命周期钩子方法componentDidMount里请求数据,此外还包含更新表单应用 state 的逻辑行为。在下面的预览代码里,我移除了表单元素的 props 和 change 事件处理方法,这样看起来更简洁清晰(拉到文章底部,可以看到完整代码)。

import React, {Component} from 'react';

import CheckboxOrRadioGroup from '../components/CheckboxOrRadioGroup';

import SingleInput from '../components/SingleInput';

import TextArea from '../components/TextArea';

import Select from '../components/Select';

class FormContainer extends Component {

constructor(props) {

super(props);

this.handleFormSubmit = this.handleFormSubmit.bind(this);

this.handleClearForm = this.handleClearForm.bind(this);

}

componentDidMount() {

fetch('./fake_db.json')

.then(res => res.json())

.then(data => {

this.setState({

ownerName: data.ownerName,

petSelections: data.petSelections,

selectedPets: data.selectedPets,

ageOptions: data.ageOptions,

ownerAgeRangeSelection: data.ownerAgeRangeSelection,

siblingOptions: data.siblingOptions,

siblingSelection: data.siblingSelection,

currentPetCount: data.currentPetCount,

description: data.description

});

});

}

handleFormSubmit() {

// 提交逻辑写在这 }

handleClearForm() {

// 清除表单逻辑写在这 }

render() {

return (

Pet Adoption Form

{/* Full name text input */}

{/* Owner age range select */}

{/* Pet type checkboxes */}

{/* Will you adopt siblings? radios */}

{/* Number of current pets number input */}

{/* Descriptions of current pets textarea */}

type="submit"

className="btn btn-primary float-right"

value="Submit"/>

className="btn btn-link float-left"

onClick={this.handleClearForm}>Clear form

);

}

我们勾勒出了应用基础结构,接下来我们一起浏览下每个子组件的细节。

组件

该组件可以是 text 或 number 输入框,这取决于传入的 props。通过 React 的 PropTypes,我们可以非常好地记录组件拿到的 props。如果漏传 props 或传入错误的数据类型, 浏览器的控制台中会出现警告信息。

下面列举 组件的 PropTypes:

SingleInput.propTypes = {

inputType: React.PropTypes.oneOf(['text'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值