受控组件
在HTML的表单元素中,它们通常自己维护一套state,并随着用户的输入自己进行UI上的更新,这种行为是不被我们程序所管控的。而如果将React里的state属性和表单元素的值建立依赖关系,再通过onChange事件与setState()结合更新state属性,就能达到控制用户输入过程中表单发生的操作。被React以这种方式控制取值的表单输入元素就叫做受控组件
上面这段描述用代码翻译大概是这样子的:
假设 HTML 中有一个这样的表单
<form>
<label>
名字:
<input type="text" name="name" />
</label>
</form>
用户在界面上的输入框输入内容时,表单元素会根据用户的输入自己进行 UI 上的更新(表单元素上抽象的 state 作用)
在 React 中,如果我们想要控制输入框内容,可以在 this.state 中定义一个 value属性,并将表单元素上的 value 指定为这个属性
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
}
render() {
return (
<form>
<label>
名字:
<input type="text" value={this.state.value} />
</label>
</form>
);
}
}
然而当我们尝试在表单元素中输入内容时就会发现这个表单元素的内容并没有进行更新,这是因为表单元素的 value 被 this.state.value 控制,当用户输入新的内容时,this.state.value 并不会自动更新。但是可以用一个 onChange 事件来监听输入内容的改变并使用 setState 更新 this.state.value
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});
}
handleSubmit(event) {
// 通过 this.state.value 获取
alert('提交的名字: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
名字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
);
}
}
这就是受控组件的常用姿势了,在表单元素上设置 value 属性,通过 onChange 事件与 setState() 结合更新 value 属性
<FInput value={x} onChange={fn}/>
非受控组件
有时我们仅仅是想要获取某个表单元素的值,而不关心它是如何改变的,那么我们可以使用 ref 来从 DOM 节点中获取表单数据,并不需要为每个状态更新都编写数据处理函数
class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}
handleSubmit(event) {
// 通过 this.input.current.value 获取
alert('A name was submitted: ' + this.input.current.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
非受控组件看起来更像传统的 HTML 表单,简单来写就是:
<FInput defaultValue={x} ref={input}/>
如何选择
大多数情况下,官方推荐使用受控组件来处理表单数据
应用场景 | 非受控组件 | 受控组件 |
---|---|---|
一次性值检索(例如提交时) | ✅ | ✅ |
提交时验证 | ✅ | ✅ |
即时验证 | ❌ | ✅ |
有条件禁用按钮 | ❌ | ✅ |
强制输入格式 | ❌ | ✅ |
一个数据的多个输入 | ❌ | ✅ |
动态输入 | ❌ | ✅ |