表单
在用户提交表单时,html的默认行为会使这个表单跳转到一个新页面,在React中也是这样。
在大多数情况下,我们都会构建一个处理提交表单并且可以访问输入数据的函数,实现这一点的标准的方法就是使用 “受控组件” 技术。
1.受控组件
在HTML中,像input
,textarea
,select
,这类表单元素都会维持自身的状态,并且可以根据用户的输入进行更新。
在React中,可变状态通常保存在组件的状态属性中,并且只能通过setState()
的方法进行更新。
我们通过使React变成一个单一的数据源来结合两者,React负责渲染表单的组件和后续控制表单被输入时发生的变化。相应的,被React的数据控制状态的表单组件被称为 受控组件。
demo
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
})
console.log(event.target.value)
}
handleSubmit(event){
alert('name:'+this.state.value);
event.preventDefault();
}
render(){
return(
<form action="">
<label htmlFor="">
Name:
<input type="text" value={this.state.value} onChange={this.handleChange}/>
</label>
<input type="button" value="Submit" onClick={this.handleSubmit}/>
</form>
)
}
}
ReactDOM.render(
<NameForm />,document.getElementById('root')
)
由于value
的值是在表单上设定的this.state.value
,所以显示的值始终绑定与React的state状态,并且每次按键输入都会触发this.handleChange()
来更新React的state,所以展示的值也会一直更新。
使用 “受控组件” 每个状态的改变,都有一个与他相关的处理函数,这样就能直接修改或者验证用户的输入。
例如:限制全部的输入为 大写字母
//修改handleChange方法
handleChange(event){
this.setState({
value:event.target.value.toUpperCase()
})
}
2.textarea标签
①在HTML中元素通过他的子节点来定义它的内容
<textarea>hello,React</ textarea>
②在React中,会使用value
属性来代替
class EssayForm extends React.Component{
constructor(props){
super(props);
this.state={
value:'please write an essay'
}
this.handleChange=this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event){
this.setState({value:event.target.value})
}
handleSubmit(event){
alert('essay:'+this.state.value);
event.preventDefault();
}
render(){
return(
<form onSubmit={this.handleSubmit}>
<label htmlFor="">
Name:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit"/>
</form>
)
}
}
ReactDOM.render(
<EssayForm />,document.getElementById('root')
)
注意this.state.value
是在构造函数中初始化,这样文本区域就能获取到其中的文本。
3.select标签
①在HTML中,select
会创建一个下拉列表,比如这个HTML就创建了一个下拉列表的原型。
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
注意:
Coconut选项上的select
由于最初被选中有一个selected属性,在React中,并不会这样使用,而是根据select
上的value
来显示选中项,这在受控组件中更加方便,因为你只需要在一个地方修改他的状态。
demo
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('choice:'+this.state.value);
event.preventDefault();
}
render(){
return(
<form action="" onSubmit={this.handleSubmit}>
<label htmlFor="">
pick your item
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">grapefruit</option>
<option value="lime">lime</option>
<option value="coconut">coconut</option>
<option value="mango">mango</option>
</select>
</label>
<input type="submit" value="Submit"/>
</form>
)
}
}
ReactDOM.render(
<FlavorForm />,document.getElementById('root')
)
总之,<input type="text">
,<textarea>
, 和 <select>
都十分类似 - 他们都通过传入一个value属性来实现对组件的控制。
4.file input标签
①在HTML中,<input type="file" />
允许用户从他们的存储设备中选择一个或者多个的文件以提交表单的形式提交到服务器,或者通过 Javascript 的 File API 对文件进行操作 。
<input type="file">
由于该标签的 value
属性是只读的, 所以它是 React 中的一个非受控组件。我们会把它和其他非受控组件一起在后面的章节进行详细的介绍。
5.多个输入的解决方法
当你处理多个受控的input
组件时,可以通过给每一个元素添加name属性,来让处理函数event.target.name
选择做些什么。
demo
class Reservation extends React.Component {
constructor(props){
super(props);
this.state={
isGoing:true,
numberOfGuests:200
}
this.handleInputChange=this.handleInputChange.bind(this);
}
handleInputChange(event){
const target = event.target;
const value = target.type==='checkbox'?target.checked:target.value;
const name = target.name;
this.setState({
[name]:value //es6语法
})
}
render(){
return(
<form action="">
<label htmlFor="">
is isGoing
<input type="text" name="isGoing" type="checkbox"
checked={this.state.isGoing} onChange={this.handleInputChnage}/>
</label>
<br/>
<label htmlFor="">
number of guests:
<input type="text" name="numberOfGuests" type="number"
value={this.state.numberOfGuests} onChange={this.handleInputChange}/>
</label>
</form>
)
}
}
ReactDOM.render(
<Reservation />,document.getElementById('root')
)
注意我们如何使用ES6当中的计算属性名语法来更新与给定输入名称相对应的状态键:
this.setState({
[name]: value
});
//相当于ES5语法如下
var partialState = {};
partialState[name] = value;
this.setState(partialState);
6.受控组件的替代方法
有时使用受控组件可能很繁琐,因为您要为数据可能发生变化的每一种方式都编写一个事件处理程序,并通过一个组件来管理全部的状态。当您将预先存在的代码库转换为React或将React应用程序与非React库集成时,这可能变得特别烦人。在以上情况下,你或许应该看看非受控组件,这是一种表单的替代技术。
网友评论