非受控组件

在大多数情况下,我们推荐使用 受控组件 来处理表单数据。在一个受控组件中,表单数据是由 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. }
  7. handleSubmit(event) {
  8. alert('A name was submitted: ' + this.input.current.value);
  9. event.preventDefault();
  10. }
  11. render() {
  12. return (
  13. <form onSubmit={this.handleSubmit}>
  14. <label>
  15. Name:
  16. <input type="text" ref={this.input} />
  17. </label>
  18. <input type="submit" value="Submit" />
  19. </form>
  20. );
  21. }
  22. }

在 CodePen 上尝试

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

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

默认值

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

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

同样,<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. }
  7. handleSubmit(event) {
  8. event.preventDefault();
  9. alert(
  10. `Selected file - ${
  11. this.fileInput.current.files[0].name
  12. }`
  13. );
  14. }
  15. render() {
  16. return (
  17. <form onSubmit={this.handleSubmit}>
  18. <label>
  19. Upload file:
  20. <input type="file" ref={this.fileInput} />
  21. </label>
  22. <br />
  23. <button type="submit">Submit</button>
  24. </form>
  25. );
  26. }
  27. }
  28. ReactDOM.render(
  29. <FileInput />,
  30. document.getElementById('root')
  31. );

在 CodePen 上尝试