概述:在大多数情况下,都建议使用受控制的组件去实现表单,在一个受控制的组件中,表单数据被React组件所处理。而它的替代就是不受控制的组件——表单数据被DOM自己处理。
(一)不受控制的组件
创建不受控制的组件,我们不再对每次state更新创建事件处理函数——可以使用引用(ref)从DOM取得数据
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>
);
}
}
因为不受控制的组件将DOM作为数据的最后来源(keep the source of truth in the DOM),而不是state,有些情况下,这样会更方便于整合React代码和非React代码。如果你非常紧急,这样也会减少一定的代码量。而在其它情况下,请使用受控制的组件!
在什么情况下该使用那种组件,请参考这篇文章。
默认值
在React渲染的生命周期中,表格元素(组件)的value属性(attribute)将会覆盖DOM中的value属性,对于不受控制的组件,你经常想要React指定一个初始值,但是不影响后续的更新——使用defaultValue属性去替换value属性。
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob"
type="text"
ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
同样的,<checkbox>、<radio>元素支持defaultChecked属性、<textarea>元素支持defaultValue属性。
(二)File Input
<input type="file" />可以使用户从设备储存上传一个或者多个文件到服务器、可以通过File API被JavaScript所控制。在React中,file input元素总是“不受控制的(uncontrolled)”,因为它的值总是取决于用户输入,而不能以编程方式产生。
你应该是用File API与这些文件进行交互,下面是一个简单的例子:
class FileInput extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
alert(
`Selected file - ${this.fileInput.files[0].name}`
);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input
type="file"
ref={input => {
this.fileInput = input;
}}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
}
ReactDOM.render(
<FileInput />,
document.getElementById('root')
);