07 【收集表单数据】
07 【收集表单数据】
在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state。例如这个纯 HTML 表单只接受一个名称:
<form><label>名字:<input type="text" name="name" /></label><input type="submit" value="提交" />
</form>
此表单具有默认的 HTML 表单行为,即在用户提交表单后浏览到新页面。如果你在 React 中执行相同的代码,它依然有效。但大多数情况下,使用 JavaScript 函数可以很方便的处理表单的提交, 同时还可以访问用户填写的表单数据。实现这种效果的标准方式是使用“受控组件”。
状态属性
表单元素有这么几种属于状态的属性:
value
,对应<input>
和<textarea>
所有checked
,对应类型为checkbox
和radio
的<input>
所有selected
,对应<option>
所有
在 HTML 中 <textarea>
的值可以由子节点(文本)赋值,但是在 React 中,要用 value
来设置。
表单元素包含以上任意一种状态属性都支持 onChange
事件监听状态值的更改。
针对这些状态属性不同的处理策略,表单元素在 React 里面有两种表现形式。
1.受控组件
在 HTML 中,表单元素(如<input>
、 <textarea>
和 <select>
)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()
来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作,被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
例如,如果我们想让前一个示例在提交时打印出名称,我们可以将表单写为受控组件:
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('提交的名字: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>名字:<input type="text" value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="提交" /></form>);}
}
在 CodePen 上尝试
由于在表单元素上设置了 value
属性,因此显示的值将始终为 this.state.value
,这使得 React 的 state 成为唯一数据源。由于 handlechange
在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。
对于受控组件来说,输入的值始终由 React 的 state 驱动。你也可以将 value 传递给其他 UI 元素,或者通过其他事件处理函数重置,但这意味着你需要编写更多的代码。
为什么要有受控组件?
引入受控组件不是说它有什么好处,而是因为 React 的 UI 渲染机制,对于表单元素不得不引入这一特殊的处理方式。
在浏览器 DOM 里面是有区分 attribute 和 property 的。attribute 是在 HTML 里指定的属性,而每个 HTML 元素在 JS 对应是一个 DOM 节点对象,这个对象拥有的属性就是 property(可以在 console 里展开一个 DOM 节点对象看一下,HTML attributes 只是对应其中的一部分属性),attribute 对应的 property 会从 attribute 拿到初始值,有些会有相同的名称,但是有些名称会不一样,比如 attribute class
对应的 property 就是 className
。(详细解释:.prop,.prop() vs .attr())
回到 React 里的 <input>
输入框,当用户输入内容的时候,输入框的 value
property 会改变,但是 value
attribute 依然会是 HTML 上指定的值(attribute 要用 setAttribute
去更改)。
React 组件必须呈现这个组件的状态视图,这个视图 HTML 是由 render
生成,所以对于
render: function() {return <input type="text" value="hello"/>;
}
在任意时刻,这个视图总是返回一个显示 hello
的输入框。
2.非受控组件
在大多数情况下,我们推荐使用 受控组件 来处理表单数据。在一个受控组件中,表单数据是由 React 组件来管理的。另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理。
2.1 基本概念
要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据。
例如,下面的代码使用非受控组件接受一个表单的值:
class NameForm extends React.Component {constructor(props) {super(props);this.handleSubmit = this.handleSubmit.bind(this);this.input = React.createRef();}handleSubmit(event) {alert('A name was submitted: ' + this.input.current.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>Name:<input type="text" ref={this.input} /></label><input type="submit" value="Submit" /></form>);}
}
在 CodePen 上尝试
因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。
如果你还是不清楚在某个特殊场景中应该使用哪种组件,那么 这篇关于受控和非受控输入组件的文章 会很有帮助。
2.2 默认值
在 React 渲染生命周期时,表单元素上的 value
将会覆盖 DOM 节点中的值。在非受控组件中,你经常希望 React 能赋予组件一个初始值,但是不去控制后续的更新。 在这种情况下, 你可以指定一个 defaultValue
属性,而不是 value
。在一个组件已经挂载之后去更新 defaultValue
属性的值,不会造成 DOM 上值的任何更新。
render() {return (<form onSubmit={this.handleSubmit}><label>Name:<inputdefaultValue="Bob"type="text"ref={this.input} /></label><input type="submit" value="Submit" /></form>);
}
同样,<input type="checkbox">
和 <input type="radio">
支持 defaultChecked
,<select>
和 <textarea>
支持 defaultValue
。
3.标签变化
3.1 textarea 标签
在 HTML 中, <textarea>
元素通过其子元素定义其文本:
<textarea>你好, 这是在 text area 里的文本
</textarea>
而在 React 中,<textarea>
使用 value
属性代替。这样,可以使得使用 <textarea>
的表单和使用单行 input 的表单非常类似:
class EssayForm extends React.Component {constructor(props) {super(props);this.state = {value: '请撰写一篇关于你喜欢的 DOM 元素的文章.'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('提交的文章: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>文章:<textarea value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="提交" /></form>);}
}
请注意,this.state.value
初始化于构造函数中,因此文本区域默认有初值。
3.2 select 标签
在 HTML 中,<select>
创建下拉列表标签。例如,如下 HTML 创建了水果相关的下拉列表:
<select><option value="grapefruit">葡萄柚</option><option value="lime">酸橙</option><option selected value="coconut">椰子</option><option value="mango">芒果</option>
</select>
请注意,由于 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('你喜欢的风味是: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>选择你喜欢的风味:<select value={this.state.value} onChange={this.handleChange}><option value="grapefruit">葡萄柚</option><option value="lime">酸橙</option><option value="coconut">椰子</option><option value="mango">芒果</option></select></label><input type="submit" value="提交" /></form>);}
}
在 CodePen 上尝试
总的来说,这使得 <input type="text">
, <textarea>
和 <select>
之类的标签都非常相似—它们都接受一个 value
属性,你可以使用它来实现受控组件。
注意
你可以将数组传递到
value
属性中,以支持在select
标签中选择多个选项:<select multiple={true} value={['B', 'C']}>
3.3 文件 input 标签
在 HTML 中,<input type="file">
可以让用户选择一个或多个文件上传到服务器,或者通过使用 File API 进行操作。
<input type="file" />
在 React 中,<input type="file" />
始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制。
您应该使用 File API 与文件进行交互。下面的例子显示了如何创建一个 DOM 节点的 ref 从而在提交表单时获取文件的信息。
class FileInput extends React.Component {constructor(props) {super(props);this.handleSubmit = this.handleSubmit.bind(this);this.fileInput = React.createRef();}handleSubmit(event) {event.preventDefault();alert(`Selected file - ${this.fileInput.current.files[0].name}`);}render() {return (<form onSubmit={this.handleSubmit}><label>Upload file:<input type="file" ref={this.fileInput} /></label><br /><button type="submit">Submit</button></form>);}
}const root = ReactDOM.createRoot(document.getElementById('root')
);
root.render(<FileInput />);
在 CodePen 上尝试
07 【收集表单数据】相关推荐
- php中的全局变量$_POST收集表单数据
< !-- php中的$POST被广泛的用于手机表单数据,在HTML中from的标签指定的该属性是method="post" 下面我们将显示一个输入的字段,以及一个提交的按钮 ...
- reactjs中收集表单数据:非受控组件和受控组件
1_非受控组件 <!DOCTYPE html> <html lang="en"> <head><meta charset="UT ...
- vue自动提交表单_(尚012)Vue表单数据的自动手集(表单数据提交,需要收集表单数据)...
自动收集,就是我一输入数据,就自动收集,等我点击提交按钮的时候,数据就收集好了 1.使用v-model对表单数据自动收集 1)text/textare----单行/多行输入框 2)checkbox-- ...
- jQuery 序列化表单数据 serialize() serializeArray()
1.serialize()方法 格式:var data = $("form").serialize(); 功能:将表单内容序列化成一个字符串. 这样在ajax提交表单数据时,就不用 ...
- Linkflow+表单工具:赋能表单数据,提升表单营销能力
前言 本文旨在帮助企业实现敏捷高效运营,提升用户数据运营效能.在这里,我们将提供Linkflow+表单工具的组合场景玩法,以帮助企业提升表单营销能力,更好实现用户精细化运营和自动化营销. 如果您有以下 ...
- php 保存表单数据,使用jquery和php自动保存表单数据
我对PHP非常好,但是使用jQuery的总菜单,并且卡在自动保存表单数据中. 自动保存功能在dummy.php中每30秒调用一次.我正在将用于处理的序列化表单数据( – >数据库)发送到save ...
- WebApi发送HTML表单数据:文件上传与多部分MIME
5.3 Sending HTML Form Data 5.3 发送HTML表单数据(2) 本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/28 ...
- php获取post表单数据_PHP如何通过post方法来获取form表单中数据?(代码示例)
我们在网站开发过程中,通常都会遇到关于php form表单的相关操作.如php获取带有post提交方法的表单数据,这种该如何操作呢?如果大家有看过我[PHP如何通过get方法获得form表单数据?]这 ...
- python表单数据系统_使用MultipartPostHandler用Python发布表单数据
问题:使用Python的urllib2发布数据时,所有数据都是URL编码的,并作为内容类型发送:application/x-www-form-URL encoded.上载文件时,应将内容类型设置为mu ...
最新文章
- PyTorch框架:(6)图像识别实战常用模块解读
- CLR Profiler 性能分析工具 (转)
- 首个中文多项选择阅读理解数据集:BERT最好成绩只有68%,86%问题需要先验知识...
- 机器学习(MACHINE LEARNING)多属性决策模型
- python流程控制-Python 流程控制
- c语言课程思政教案设计,设计类专业课程思政教学案例及教学设计
- python中引用上层路径
- mysql导出表部分数据
- 上岸 | 震惊!211高校硕士毕业后,我在非洲当酋长!
- Javascript——Math对象
- 记一次自动提醒钉钉机器人的诞生
- 在Excel中快速制作分区桌面壁纸
- centos是什么linux操作系统,CentOS系统是什么
- Flutter 旋转动画
- 抖音GIF表情包制作教程 如何制作QQ动态表情包
- ckplayer在线播放流媒体
- 【OpenCV 例程200篇】220.对图像进行马赛克处理
- 英文Essay写作中存在哪些门道?
- 华北赛区承办学校:太原工业学院
- 本溪市公安局诉求电话
热门文章
- 什么是MVC和MVVC,以及它们的区别
- 2019年一月十日 Mixin Network 资产持有量快照
- LinkedList的模拟实现(Java实现)
- android手机桌面管理,Android桌面管理
- CES2017盘点: 各大公司都推出了哪些机器人
- 聚类算法-K-means-C++实现
- linux安装TBase v2.5
- python describe函数_Python pandas.DataFrame.describe函数方法的使用
- win 10家庭版升专业版报错:0xC004F069在运行Microsoft Windows非核心版本的计算机上……
- 湛蓝.Net代码生成器发布了