包含表单的组件分为受控组件与非受控组件,下面我们通过一个实例进行讲解。
实例
需求:定义一个包含表单的组件,输入用户名密码后,点击登录提示输入信息。
非受控组件
非受控组件,就是需要数据的时候现取现用。
// 创建组件
class Login extends React.Component{
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username, password} = this
alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render(){
return (
<form onSubmit={this.handleSubmit}>
用户名:<input ref={c => this.username = c}type="text" name="username"/>
密码:<input ref={c => this.password = c} type="text" name="password"/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Login/>, document.getElementById('test'))
受控组件
受控组件就是把需要的数据保存在 state
中,之后要用的时候,直接从 state
中即可。
// 创建组件
class Login extends React.Component{
// 初始化状态
state = {
username:'', //用户名
password:'' //密码
}
saveUsername = (event)=>{
this.setState=({username:event.target.value})
}
savePassword = (event)=>{
this.setState=({password:event.target.value})
}
// 表单提交的回报
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username, password} = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
render(){
return (
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveUsername} type="text" name="username"/>
密码:<input onChange={this.savePassword} type="text" name="password"/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Login/>, document.getElementById('test'))
上面就是使用了受控组件,但是每个都使用不同的回调函数,当表单需要收集的东西变多的时候,就需要定义很多回调函数,这样代码看着就很冗余。下面我们通过一个函数完成所有回调函数。
// 创建组件
class Login extends React.Component{
// 初始化状态
state = {
username:'', //用户名
password:'' //密码
}
saveFormData = (dataType)=>{
return (event)=>{
this.setState({[dataType]:event.target.value})
}
}
// 表单提交的回报
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username, password} = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
render(){
return (
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
密码:<input onChange={this.saveFormData('password')} type="text" name="password"/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Login/>, document.getElementById('test'))
因为 onChange
需要一个回调函数,所以我们 return
一个函数,这里就要提到高阶函数与函数柯里化的概念。
高阶函数
- 若一个函数,接收的参数是一个函数,那么这个函数就可以被称为高阶函数。
- 若一个函数,调用的返回值依然是一个函数,那么这个就可以被称为高阶函数。
常见的高阶函数有:Promise
、setTimeout
、arr.map()
等等。
函数的柯里化
通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式,比如上面的 saveFormData
。
当然我们不使用函数的柯里化也可以解决这个问题。
// 创建组件
class Login extends React.Component{
// 初始化状态
state = {
username:'', //用户名
password:'' //密码
}
saveFormData = (dataType, event)=>{
this.setState({[dataType]:event.target.value})
}
// 表单提交的回报
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username, password} = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
render(){
return (
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={event => this.saveFormData('username', event)} type="text" name="username"/>
密码:<input onChange={event => this.saveFormData('password', event)} type="text" name="password"/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Login/>, document.getElementById('test'))
我们通过回传一个箭头函数来解决这个问题。