受控组件
React里面,HTML的表单元素工作方式和其他DOM不太一样。表单元素通常会维护内部的状态,这些状态会根据用户的输入而更新。而React中,可变状态通常保存在state中,并且只能通过setState更新。
所以React就把这两种方式结合起来,让state成为React的“唯一数据源”。并且React还控制着用户的输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
所谓的受控组件和非受控组件,是针对表单元素而言的。
受控组件有以下几个特点:
- 表单元素依赖于状态,它的值始终由React的state来驱动。
- 表单元素的修改,会实时映射到state,跟双向绑定类似。
- 必须继承React.Component
- 受控组件必须在表单上使用onChange来绑定事件
常见的受控组件
- input
class InputForm extends React.Component {
constructor(props){
this.state = {
value: ''
}
}
this.handleChange = handleChange.bind(this);
handleChange(e){
this.setState({value: e.target.value})
}
render(){
return (
<form>
<input
value={this.state.value}
onChange={this.handleChange}
/>
</form>
)
}
}
但如果input标签的type取值为“file”,它的value是只读的,所以它是非受控组件。
- textarea
class TextAreaForm extends React.Component {
constructor(){
this.state = {
value: "默认文本"
}
}
render(){
return (
<textarea
value={this.state.value}
onChange={(e) => {this.setState({value: e.target.value})}}
/>
)
}
}
-
select
React不会使用selected属性,而是在selected标签里用value表示选中项。
对于多选框。可以在value里传入一个数组。
class SelectForm extends React.Component {
cosntructor(){
this.state = {
value: "item1"
// value: ["item1", "item2"]
}
}
render(){
return (
<select
{/* mutiply={true} */}
value={this.state.value}
onChange={(e) => {this.setState({e.target.value})}}
>
<option value="item1">item1</option>
<option value="item2">item2</option>
<option value="item3">item3</option>
</select>
)
}
}
注意:
-
我们必须给受控组件添加onChange事件监听函数,否则浏览器会报错:
解决办法:设置readOnly属性或者添加onChange函数
-
当我们给input的value属性指定一个和state相关的值,或者没有在onChange函数中写setState逻辑,会阻止用户的输入,但指定null或undefined除外:
// 用户无法输入
<input value="hi"/>
<input value={this.state.value} onChange={()=>{}}
// 用户可以输入
<input value={null} />
<input value={undefined} />
有时候,使用受控组件是件很麻烦的事情,需要为数据变化的每一种方式都编写处理函数,并通过一个React组件传递所有的state。如果将非React代码转成React代码或者做React代码和非React代码集成时,会非常繁琐。这些情况下,可以引用非受控组件——表单的另一种实现方式。
参考资料: