应用表单组件
- 文本框
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleTextareaChange = this.handleTextareaChange.bind(this);
this.state = {
inputValue: '',
textareaValue: '',
};
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value,
});
}
handleTextareaChange(e) {
this.setState({
textareaValue: e.target.value,
});
}
render() {
const { inputValue, textareaValue } = this.state;
return (
<div>
<p>单行输入框:<input type="text" value={inputValue}
onChange={this.handleInputChange} /></p>
<p>多行输入框:<textarea value={textareaValue}
onChange={this.handleTextareaChange} /></p>
</div>
);
}
}
- 单选按钮与复选框
- 单选框
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handeChange = this
.handleChange
.bind(this);
this.state = {
radioValue: ''
};
}
handleChange(e) {
this.setState({ radioValue: e.target.value });
}
render() {
const { radioValue } = this.state;
return (
<div>
<p>gender:</p>
<label>
male:
<input
type="radio"
value="male"
checked={radioValue === 'male'}
onChange={this.handleChange} />
</label>
<label>
female:
<input
type="radio"
value="female"
checked={radioValue === 'female'}
onChange={this.handleChange} />
</label>
</div>
);
}
}
- 多选框
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleChange = this
.handleChange
.bind(this);
this.state = {
coffee: []
};
}
handleChange(e) {
const {checked, value} = e.target;
let {coffee} = this.state;
if (checked && coffee.indexOf(value) === -1) {
coffee.push(value);
} else {
coffee = coffee.filter(i => i !== value);
}
this.setState({coffee});
}
render() {
const {coffee} = this.state;
return (
<div>
<p>请选择你最喜欢的咖啡:</p>
<label>
<input
type="checkbox"
value="Cappuccino"
checked={coffee.indexOf('Cappuccino') !== -1}
onChange={this.handleChange}/>
Cappuccino
</label>
<br/>
<label>
<input
type="checkbox"
value="CafeMocha"
checked={coffee.indexOf('CafeMocha') !== -1}
onChange={this.handleChange}/>
CafeMocha
</label>
<br/>
<label>
<input
type="checkbox"
value="CaffeLatte"
checked={coffee.indexOf('CaffeLatte') !== -1}
onChange={this.handleChange}/>
Caffè Latte
</label>
<br/>
<label>
<input
type="checkbox"
value="Machiatto"
checked={coffee.indexOf('Machiatto') !== -1}
onChange={this.handleChange}/>
Machiatto
</label>
</div>
);
}
}
- Select 组件
- 单选
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleChange = this
.handleChange
.bind(this);
this.state = {
area: ''
};
}
handleChange(e) {
this.setState({area: e.target.value});
}
render() {
const {area} = this.state;
return (
<select value={area} onChange={this.handleChange}>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="hangzhou">杭州</option>
</select>
);
}
}
- 多选
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleChange = this
.handleChange
.bind(this);
this.state = {
area: ['beijing', 'shanghai']
};
}
handleChange(e) {
const {options} = e.target;
// 注意,这里返回的 options 是一个对象,并非数组
const area = Object
.keys(options)
.filter(i => options[i].selected === true)
.map(i => options[i].value);
this.setState({area});
}
render() {
const {area} = this.state;
return (
<select multiple={true} value={area} onChange={this.handleChange}>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="hangzhou">杭州</option>
</select>
);
}
}
受控组件
总结下 React 受控组件更新 state 的流程:
- 可以通过在初始 state 中设置表单的默认值。
- 每当表单的值发生变化时,调用 onChange 事件处理器。
- 事件处理器通过合成事件对象 e 拿到改变后的状态,并更新应用的 state。
- setState 触发视图的重新渲染,完成表单组件值的更新。
在 React 中,数据是单向流动的。表单的数据源于组件的 state,并 通过 props 传入,这也称为单向数据绑定。然后,我们又通过 onChange 事件处理器将新的表单数 据写回到组件的 state,完成了双向数据绑定。
非受控组件
如果一个表单组件没有 value props(单选按钮和复选框对应的是 checked prop) 时,就可以称为非受控组件。相应地,你可以使用 defaultValue 和 defaultChecked prop 来表示 组件的默认状态。
对比受控组件和非受控组件
通过 defaultValue 或者 defaultChecked 来设置表单的默认值,它仅会被渲染 一次,在后续的渲染时并不起作用
面对比以下两个示例:
将输入的字母转化为大写展示:
<input
value={this.state.value}
onChange={e => {
this.setState({ value: e.target.value.toUpperCase() })
}}
/>
直接展示输入的字母:
<input
defaultValue={this.state.value}
onChange={e => {
this.setState({ value: e.target.value.toUpperCase() })
}}
/>
使用一个事件处理器来处理多个表单域
import React, {Component} from 'react';
class FormApp extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
age: 18
};
}
handleChange(name, e) {
const {value} = e.target;
// 这里只能处理直接赋值这种简单的情况,复杂的处理建议使用 switch(name) 语句
this.setState({[name]: value});
}
render() {
const {name, age} = this.state;
return (
<div>
<input
value={name}
onChange={this
.handleChange
.bind(this, 'name')}/>
<input
value={age}
onChange={this
.handleChange
.bind(this, 'age')}/>
</div>
);
}
}
表单组件的几个重要属性
-
状态属性
- value :类型为 text 的 input 组件、textarea 组件以及 select 组件都借助 value prop 来展示 应用的状态。
- checked :类型为 radio 或 checkbox 的组件借助值为 boolean 类型的 selected prop 来展示 应用的状态。
- selected :该属性可作用于 select 组件下面的 option 上,React 并不建议使用这种方式表 示状态,而推荐在 select 组件上使用 value 的方式。
-
事件属性
刚刚提到的状态属性与事件属性存在一定的关联——在状态属性发生变化时,会触发 onChange 事件属性。同样,React 支持 DOM Level 3 中定义的所有表单事件。