我们一般讨论到受控组件与非受控组件都是与表单有关的。
什么是受控组件
在React中,HTML表单的处理方式和普通的DOM元素不太一样:表单元素通常会保存在一些内部的state
比如下面的HTML表单元素:
- 这个处理方式是DOM默认处理HTML表单的行为,在用户点击提交时会提交到某个服务器中,并且刷新页面(action传后端,前后端分离之前经常用,比如jsp代码)
- 在React中,并没有禁止这个行为,它依然是有效的
- 但是通常情况下会使用JavaScript函数来方便的处理表单提交,同时还可以访问用户填写的表单数据
- 实现这种效果的标准方式是使用“受控组件”
- 在 HTML 中,表单元素(如< input >、 < textarea> 和 < select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。
- 而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
- 我们将两者结合起来,使React的state成为“唯一数据源“
- 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作
- 被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”
受控组件的基本使用
代码如下:
当我们点击提交后,会自动的产生默认行为。
我们取消掉默认行为
我们监听input框
我们用react的浏览器插件来看(保存是没问题的)
我们还要做一个操作。让value永远和this.state.username保持一致。
当前这个组件就是个受控组件
。有了受控组件我们点击提交就很方便了。
代码
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = { //每个input建议都在state里做一个保存
username: ""
}
}
render() {
return (
<div>
{/* 我们把默认行为取消掉 */}
<form onSubmit={e => this.handleSubmit(e)}>
<label htmlFor="username">
用户:
{/* 受控组件 */}
<input type="text"
id="username"
// 传入事件
onChange={e => this.handleChange(e)}
value={this.state.username}
/>
</label>
<input type="submit" value="提交"/>
</form>
</div>
)
}
handleSubmit(event) { //这个event合成事件有所有的原生事件
event.preventDefault(); //取消默认行为
}
handleChange(event) {
// console.log(event.target.value);
this.setState({
username:event.target.value
})
}
}
受控组件-select的基本使用
select会稍微有一点不一样,不过大体一致。
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
fruits: "orange" //默认值
}
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
<select name="fruits"
onChange={e => this.handleChange(e)}
value={this.state.fruits}>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<input type="submit" value="提交"/>
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state.fruits);
}
handleChange(event) {
this.setState({
fruits: event.target.value
})
}
}
受控组件多输入的情况
这个考验的还是抽离公共部分的能力。
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props){
super(props)
this.state = {
username:"",
password:"",
valid:""
}
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
<label htmlFor="">
用户:
{/* 受控组件 */}
<input type="text"
id='username'
name = "username"
onChange = {e => this.handleChange(e)}
value = {this.state.username}
/>
</label>
<input type="submit" value="提交"/>
<br />
<label htmlFor="">
密码:
{/* 受控组件 */}
<input type="text"
id='password'
name = "password"
onChange = {e => this.handleChange(e)}
value = {this.state.password}
/>
</label>
<input type="submit" value="提交"/>
<br />
<label htmlFor="">
验证:
{/* 受控组件 */}
<input type="text"
id='valid'
name = "valid"
onChange = {e => this.handleChange(e)}
value = {this.state.valid}
/>
</label>
<input type="submit" value="提交"/>
</form>
</div>
)
}
handleSubmit(event){
event.preventDefault() //取消默认事件
}
// handleUserChange(event){
// // console.log(event.target.value);
// this.setState({
// username:event.target.value
// })
// }
// handlePassChange(event){
// this.setState({
// password:event.target.value
// })
// }
// handlePassChange(event){
// this.setState({
// valid:event.target.value
// })
// }
handleChange(event){
this.setState({
// []:event.target.value ES6新语法:计算属性名
[event.target.name]:event.target.value
})
}
}
非受控组件
在开发中不建议大家来使用。 非受控组件还是操作dom了,react中只要直接操作dom就不建议。
import React, { PureComponent, createRef } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.usernameRef = createRef();
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
<label htmlFor="username">
用户:
<input type="text" id="username" ref={this.usernameRef}/>
</label>
<input type="submit" value="提交"/>
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
console.log(this.usernameRef.current.value);
}
}