表单元素是一类拥有内部状态的元素,这些状态由其自身维护,通过这类元素可让用户与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}/>女
</>
);
}
}

React躬行记(7)——表单的更多相关文章

  1. React躬行记(5)——React和DOM

    React实现了一套与浏览器无关的DOM系统,包括元素渲染.节点查询.事件处理等机制. 一.ReactDOM 自React v0.14开始,官方将与DOM相关的操作从React中剥离,组成单独的rea ...

  2. React躬行记(8)——样式

    由于React推崇组件模式,因此会要求HTML.CSS和JavaScript混合在一起,虽然这与过去的关注点分离正好相反,但是更有利于组件之间的隔离.React已将HTML用JSX封装,而对CSS只进 ...

  3. React躬行记(3)——组件

    组件(Component)由若干个React元素组成,包含属性.状态和生命周期等部分,满足独立.可复用.高内聚和低耦合等设计原则,每个React应用程序都是由一个个的组件搭建而成,即组成React应用 ...

  4. React躬行记(13)——React Router

    在网络工程中,路由能保证信息从源地址传输到正确地目的地址,避免在互联网中迷失方向.而前端应用中的路由,其功能与之类似,也是保证信息的准确性,只不过来源变成URL,目的地变成HTML页面. 在传统的前端 ...

  5. React躬行记(2)——JSX

    JSX既不是字符串,也不是HTML,而是一种类似XML,用于描述用户界面的JavaScript扩展语法,如下代码所示.在使用JSX时,为了避免自动插入分号时出现问题,推荐在其最外层用圆括号包裹,并且必 ...

  6. React躬行记(4)——生命周期

    组件的生命周期(Life Cycle)包含三个阶段:挂载(Mounting).更新(Updating)和卸载(Unmounting),在每个阶段都会有相应的回调方法(也叫钩子)可供选择,从而能更好的控 ...

  7. React躬行记(6)——事件

    React在原生事件的基础上,重新设计了一套跨浏览器的合成事件(SyntheticEvent),在事件传播.注册方式.事件对象等多个方面都做了特别的处理. 一.注册事件 合成事件采用声明式的注册方式, ...

  8. React躬行记(9)——组件通信

    根据组件之间的嵌套关系(即层级关系)可分为4种通信方式:父子.兄弟.跨级和无级. 一.父子通信 在React中,数据是自顶向下单向流动的,而父组件通过props向子组件传递需要的信息是组件之间最常见的 ...

  9. React躬行记(10)——高阶组件

    高阶组件(High Order Component,简称HOC)不是一个真的组件,而是一个没有副作用的纯函数,以组件作为参数,返回一个功能增强的新组件,在很多第三方库(例如Redux.Relay等)中 ...

随机推荐

  1. 在WPF程序中将控件所呈现的内容保存成图像

    原文:在WPF程序中将控件所呈现的内容保存成图像 有的时候,我们需要将控件所呈现的内容保存成图像保存下来,例如:InkCanvas的手写墨迹,WebBrowser中的网页等.可能有人会说,这个不就是截 ...

  2. python脚本,重新设置图片大小

    最近在做一个android的电台,此android程序要访问自己服务器上的歌曲文件,包括图片.这些文件要自己手动上传. 每天十首歌,需要二十个图片(一个大图450*450.一个小图140*140). ...

  3. Ruby已经慢慢走向衰退了,那些年代久远而且小众的语言没有翻身的可能性

    Ruby已经慢慢走向衰退了,现在WEB开发里,NODE.JS+前端各种框架是主流,PHP.ruby.Asp.net.python等语言在网站编程方面只会越来越少.数据领域方面,机器学习和人工智能中,p ...

  4. 高斯判别分析模型( Gaussian discriminant analysis)及Python实现

    高斯判别分析模型( Gaussian discriminant analysis)及Python实现 http://www.cnblogs.com/sumai 1.模型 高斯判别分析模型是一种生成模型 ...

  5. CSS3 Maker提供了10个最为常用的CSS3属性在线生成工具

    CSS3 Maker提供了10个最为常用的CSS3属性在线生成工具,比如说border-radius.gradient.transfrom.animation.transition.rgba.text ...

  6. Qt实现网络播放器

        写了这么多的博客,关于网络的还不算多,经常有人询问一些关于网络传输.制作在线试听及下载音乐.构造及解析数据等的一些问题,今天就在这里一并讲解.   网络操作:     主要涉及:QNetwor ...

  7. c#与JAVA利用SOCKET实现异步通信的SanNiuSignal.DLL已开源

    大家好,前段时间C#的SanNiuSignal.DLL已开源;因部分用户特需要JAVA版的SanNiuSignal;现在只能把半成品先拿出来暂时给他们用了,以后再慢慢改进; JAVA版目前已实现跟C# ...

  8. 使用C#的HttpWebRequest模拟登陆访问人人网

    使用任何语言做模拟登陆或者抓取访问页面,无外乎以下思路: 第一 启用一个web访问会话方法或者实例化一个web访问类,如.net中的HttpWebRequest:第二 模拟POST或者GET方式提交的 ...

  9. 浅析 C++ 调用 Python 模块

    浅析 C++ 调用 Python 模块 作为一种胶水语言,Python 能够很容易地调用 C . C++ 等语言,也能够通过其他语言调用 Python 的模块. Python 提供了 C++ 库,使得 ...

  10. java反射机制获取自定义注解值和方法

    由于工作需求要应用到java反射机制,就做了一下功能demo想到这些就做了一下记录 这个demo目的是实现动态获取到定时器的方法好注解名称,废话不多说了直接上源码 1.首先需要自定义注解类 /** * ...