受控组件与不受控组件
1. 受控组件(Controlled Components)
在HTML中,表单组件<input>
,<textarea>
,<select>
拥有自身的状态(值),并根据用户的输入进行更新。而在React中,可变状态保存在state
中,并只能使用setState()
来更新。
我们可以将这两种状态合一,使React的state
成为单一数据源(single source of truth),这时渲染form的React组件就可以对表单中的输入进行控制。因此,受控组件就是值受React控制的表单输入元素。
受控组件通过change
事件(在用户输入每个字符时触发)和value
属性实现。
class NameForm extends React.Component{
constructor(props){
super(props);
this.state = {
name:'',
sex:'male',
profile:''
};
this.handleNameChange = this.handleNameChange.bind(this);
this.handleSexChange = this.handleSexChange.bind(this);
this.handleProfileChange = this.handleProfileChange.bind(this);
},
handleNameChange(e){
this.setState({name:e.target.value});
},
handleSexChange(e){
this.setState({sex:e.target.value});
},
handleProfileChange(e){
this.setState({profile:e.target.value});
},
render(){
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text"
value={this.state.name}
onChange={this.handleNameChange}
/>
</label>
<label>
Sex:
<select value={this.state.sex} onChange={this.handleSexChange}>
<option value="male">male</option>
<option value="female">female</option>
</select>
</label>
<label>
Profile:
<textarea value={this.state.profile}
onChange={this.handleProfileChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
)
}
}
受控组件通过value
属性控制输入元素的值,通过change
事件处理函数处理所有的用户输入。
如果value
设置为一个固定的值,而未设置其change
事件处理函数来设置state
,输入元素是不可编辑的。
value
属性在设置为null
或者undefined
时,输入元素仍旧是可编辑的。
受控组件需要编写每个输入元素的处理函数,比较繁琐,对于某些输入处理逻辑相同的元素,可通过name
属性统一处理。
class MultipleInput extends React.Component{
constructor(props){
super(props);
this.state = {
address:'',
alternateAddress:''
}
this.handleChange = this.handleChange.bind(this);
},
handleChange(e){
this.setState({
[e.target.name]:e.target.value
});
}
render(){
return (
<form>
<label>
address:
<input type="text"
name="address"
value={this.state.address}
onChange={this.handleChange}
/>
</label>
<label>
alternate address:
<input type="text"
name="alternateAddress"
value={this.state.alternateAddress}
onChange={this.handleChange}
/>
</label>
</form>
);
}
}
2. 不受控组件(Uncontrolled Components)
受控组件表单的值由React控制,不受控组件表单的值由DOM控制,其单一数据源保存在DOM中。
不受控组件不需要对每个输入元素编写change
事件处理函数来更新状态。在需要获取输入元素的值时可使用ref
。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
alert('A name was submitted: ' + this.input.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
React的value
属性会覆盖DOM中表单输入元素的value
值。使用不受控组件时,可使用defaultValue
属性来指定初始值。
3. 使用场景
场景 | 受控组件 | 不受控组件 |
---|---|---|
one-time value retrieval (e.g. on submit) | ✅ | ✅ |
validating on submit | ✅ | ✅ |
instant field validation | ❌ | ✅ |
conditionally disabling submit button | ❌ | ✅ |
enforcing input format | ❌ | ✅ |
several inputs for one piece of data | ❌ | ✅ |
dynamic inputs | ❌ | ✅ |