非受控组件
就如传统的 HTML 表单
class Form extends Component {
render() {
return (
<div>
<input type="text" />
</div>
);
}
}
使用一个 ref 来得到表单控件的值
class Form extends Component {
handleSubmitClick = () => {
const name = this._name.value;
// do something with `name`
}
render() {
return (
<div>
<input type="text" ref={input => this._name = input} />
<button onClick={this.handleSubmitClick}>Sign up</button>
</div>
);
}
}
换言之,当你需要时,可以从 input 中拉取值 ( pull )。这是一个最简单的方法去实现 form input 的取值。这是一个明确有效的方案。 在实际开发中,对于简单的表单可以使用非受控组件来操作。
受控组件
受控组件接收一个当前值的 prop,并且也要有一个回调来改变这个值。
这是一个更接近于 React 的方式 来处理表单的方式,但不意味应该就总是这样使用受控组件。
<input value={someValue} onChange={handleChange} />
受控组件中的值必需常驻于 state 里。跟 input 相关的渲染表单组件要保存在 state。
当然也可以保存至其它的组件的 state,即通过 props,传递另外组件的 state。又或者 Redux 也通过 props 传递过来。
每次输入新的字符时,handleNameChange
都会调用。以一个新的值设置至 state
- 开始 state.name 是空字符串
- 输入一个
a
来使handleNameChange
得到一个a
,然后调用setState
。然后这个组件重新渲染得到值a
- 再输入一个
b
。handleNameChange
得到一个ab
的值,然后设置state
。组件再次渲染,现在value="ab"
类似这种把值推进( push )表单组件的流,表单组件总会有当前 Input 的值而不需要明确地询问其值 。意味 state 与 input 的值是同步绑在一起了。
也意味会 state 会立即反映表单的改变,如
- 适当的反馈,如验证
- 按键会根据所有表单的合法性来开启 disabled
- 强制输入一些明确格式,如信用卡号
如果不这上面这些情况,可以考虑使用非受控组件。
一人上表单元素成为受控组件,要通过一个 prop。不同表单元素可能要通过不同的 prop 来设置其值:
元素 | 属性值 | 回调函数 | 回调通过什么取得新值 |
---|---|---|---|
value=”string” | onChange | event.target.value | |
checked={boolean} | onChange | event.target.checked | |
checked={boolean} | onChange | event.target.checked | |
value=”string” | onChange | event.target.value | |
value=”option value” | onChange | event.target.value |
结论
受控与非受控表单都 有各自的优点。评估现在的情况而选择最佳的方案:
如果 UI 反馈是简单的,非受控组件用 refs 是没有问题的。不需要听那些文章说非受控组件是不行的。
特征 | 非受控组件 | 受控组件 |
---|---|---|
只有一次获取值的 (如: submit) | ✅ | ✅ |
提交需要验证 | ✅ | ✅ |
即时的表单验证 | ❌ | ✅ |
根据情况来 disable 按键的 | ❌ | ✅ |
当输入时强制格式化的 | ❌ | ✅ |
有几个 input 且是一组数据的 | ❌ | ✅ |
动态 input | ❌ | ✅ |