非受控组件

在大多数情况下,我们推荐使用 受控组件 来处理表单数据。在一个受控组件中,表单数据是由 React 组件来管理的。另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理。

要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据。

例如,下面的代码使用非受控组件接受一个表单的值:

  1. class NameForm extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.handleSubmit = this.handleSubmit.bind(this);
  5. this.input = React.createRef(); }
  6. handleSubmit(event) {
  7. alert('A name was submitted: ' + this.input.current.value); event.preventDefault();
  8. }
  9. render() {
  10. return (
  11. <form onSubmit={this.handleSubmit}>
  12. <label>
  13. Name:
  14. <input type="text" ref={this.input} /> </label>
  15. <input type="submit" value="Submit" />
  16. </form>
  17. );
  18. }
  19. }

在 CodePen 上尝试

因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。

如果你还是不清楚在某个特殊场景中应该使用哪种组件,那么 这篇关于受控和非受控输入组件的文章 会很有帮助。

默认值

在 React 渲染生命周期时,表单元素上的 value 将会覆盖 DOM 节点中的值。在非受控组件中,你经常希望 React 能赋予组件一个初始值,但是不去控制后续的更新。 在这种情况下, 你可以指定一个 defaultValue 属性,而不是 value。在一个组件已经挂载之后去更新 defaultValue 属性的值,不会造成 DOM 上值的任何更新。

  1. render() {
  2. return (
  3. <form onSubmit={this.handleSubmit}>
  4. <label>
  5. Name:
  6. <input
  7. defaultValue="Bob" type="text"
  8. ref={this.input} />
  9. </label>
  10. <input type="submit" value="Submit" />
  11. </form>
  12. );
  13. }

同样,<input type="checkbox"><input type="radio"> 支持 defaultChecked<select><textarea> 支持 defaultValue

文件输入

在 HTML 中,<input type="file"> 可以让用户选择一个或多个文件上传到服务器,或者通过使用 File API 进行操作。

  1. <input type="file" />

在 React 中,<input type="file" /> 始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制。

您应该使用 File API 与文件进行交互。下面的例子显示了如何创建一个 DOM 节点的 ref 从而在提交表单时获取文件的信息。

  1. class FileInput extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.handleSubmit = this.handleSubmit.bind(this);
  5. this.fileInput = React.createRef(); }
  6. handleSubmit(event) {
  7. event.preventDefault();
  8. alert(
  9. `Selected file - ${this.fileInput.current.files[0].name}` );
  10. }
  11. render() {
  12. return (
  13. <form onSubmit={this.handleSubmit}>
  14. <label>
  15. Upload file:
  16. <input type="file" ref={this.fileInput} /> </label>
  17. <br />
  18. <button type="submit">Submit</button>
  19. </form>
  20. );
  21. }
  22. }
  23. ReactDOM.render(
  24. <FileInput />,
  25. document.getElementById('root')
  26. );

在 CodePen 上尝试