Appearance
受控组件-非受控组件
本节目标:理解“受控组件-非受控组件”的核心思路,并能把它用于实际开发或面试表达。
**受控组件是指:**双向绑定:表单的值和props或state进行了双向绑定;表单的值由组件的props或state控制;变化更新state:当表单的值发生变化时,组件对应的state或props也发生变化;
**非受控组件**组件的props或state只设置表单项的初始值;表单值的变化不会引起props或state的变化;不编写表单状态更新的数据处理函数;通过ref从Dom节点中来获取表单数据,比如:ref.current.value或ref.current.files[0](文件表单)在大多数情况下,推荐使用 受控组件 来处理表单数据。 替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理。
**应用举例**
例如,下面的代码使用非受控组件接受一个表单的值:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.input = React.createRef();
}
handleSubmit(event) {
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>
);
}
}
因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。**默认值**
在 React 渲染生命周期时,表单元素上的 value 将会覆盖 DOM 节点中的值,在非受控组件中,你经常希望 React 能赋予组件一个初始值,但是不去控制后续的更新。 在这种情况下, 你可以指定一个 defaultValue 属性,而不是 value。
render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input defaultValue="Bob" type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> );}
同样,<input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,<select> 和 <textarea> 支持 defaultValue。**文件输入**
**<****input** **type****="****file****" />**可以让用户选择一个或多个文件上传到服务器,或者通过使用 File API 进行操作。
在 React 中,****<input type="file" /> 始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制。
您应该使用 File API 与文件进行交互。下面的例子显示了如何创建一个 [DOM](https://react.docschina.org/docs/refs-and-the-dom.html) 节点的 ref 从而在提交表单时获取文件的信息。
class FileInput extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.fileInput = React.createRef();
}
handleSubmit(event) {
event.preventDefault();
alert(
`Selected file - ${this.fileInput.current.files[0].name}`);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>Upload file:
<input type="file" ref={this.fileInput} />
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
}
ReactDOM.render(
<FileInput />,
document.getElementById('root')
);> 来自
<https://react.docschina.org/docs/uncontrolled-components.html>