1、受控组件
React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 [setState()](https://zh-hans.reactjs.org/docs/react-component.html#setstate)来更新。
表单元素(如<input>、 <textarea> 和 <select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。
A.input标签
class NameForm extends React.Component {constructor(props) {super(props);this.state = {value: ''};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('提交的名字: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>名字:<input type="text" value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="提交" /></form>);}}
由于在表单元素上设置了 value 属性,因此显示的值将始终为 this.state.value,这使得 React 的 state 成为唯一数据源。由于 handlechange 在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。
对于受控组件来说,每个 state 突变都有一个相关的处理函数。这方便了修改或验证用户输入。例如,强制要求所有名称都用大写字母书写,可以将 handlechange 改写为:
handleChange(event) {this.setState({value: event.target.value.toUpperCase()});}
B.textarea 标签
class EssayForm extends React.Component {constructor(props) {super(props);this.state = {value: '请撰写一篇关于你喜欢的 DOM 元素的文章.'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('提交的文章: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>文章:<textarea value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="提交" /></form>);}}
C.select 标签
class FlavorForm extends React.Component {constructor(props) {super(props);this.state = {value: 'coconut'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('你喜欢的风味是: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>选择你喜欢的风味:<select value={this.state.value} onChange={this.handleChange}><option value="grapefruit">葡萄柚</option><option value="lime">酸橙</option><option value="coconut">椰子</option><option value="mango">芒果</option></select></label><input type="submit" value="提交" /></form>);}}
D.处理多个输入
需要处理多个 input 元素时,可以给每个元素添加 name 属性,并让处理函数根据 event.target.name 的值选择要执行的操作。
class Reservation extends React.Component {constructor(props) {super(props);this.state = {isGoing: true,numberOfGuests: 2};this.handleInputChange = this.handleInputChange.bind(this);}handleInputChange(event) {const target = event.target;const value = target.type === 'checkbox' ? target.checked : target.value;const name = target.name;this.setState({[name]: value});}render() {return (<form><label>参与:<inputname="isGoing"type="checkbox"checked={this.state.isGoing}onChange={this.handleInputChange} /></label><br /><label>来宾人数:<inputname="numberOfGuests"type="number"value={this.state.numberOfGuests}onChange={this.handleInputChange} /></label></form>);}}
E.受控输入空值
在受控组件上指定 value 的 prop 可以防止用户更改输入。如果指定了 value,但输入仍可编辑,则可能是意外地将value 设置为 undefined 或 null。
输入最初被锁定,但在短时间延迟后变为可编辑。
ReactDOM.render(<input value="hi" />, mountNode);setTimeout(function() {ReactDOM.render(<input value={null} />, mountNode);}, 1000);
2、非受控组件
编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,可以 使用 ref 来从 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>);}}
A.文件 input 标签
创建一个 DOM 节点的 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'));
3、为表单组件指定默认值
在 React 渲染生命周期时,表单元素上的 value 将会覆盖 DOM 节点中的值,在非受控组件中,你经常希望 React 能赋予组件一个初始值,但是不去控制后续的更新。 在这种情况下, 可以指定一个 defaultValue 属性,而不是 value。
<input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked <select> 和 <textarea> 支持 defaultValue。
render() {return (<form onSubmit={this.handleSubmit}><label>Name:<inputdefaultValue="Bob"type="text"ref={this.input} /></label><input type="submit" value="Submit" /></form>);}
