React入门(七) | 青训营笔记

80 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天

这篇笔记记录了React中收集表单数据的一些知识

一、本堂课重点内容

  • 收集表单数据的知识点

二、详细知识点介绍

1、非受控组件定义

  • 受控与非受控是从组件的角度出发来说出的概念,字面意思就是组件是不被控制的,不被谁控制,当然是不被父组件控制,那么不受控制的组件的特性就是一切逻辑只与自身有关,与其他的组件没有通信与交集
  • 在HTML当中,像inputcheckbox等这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,这些组件在不加以处理的情况下都是非受控组件,因为真正使用的时候会发现这些组件是不会自动更新值的,我们输入的值在不做任何处理的情况是无法拿到使用输入的值的
  • 非受控的组件的组件状态并不受外部环境控制,而是封闭在组件内部
  • 非受控组件的数据是现用现取的,需要用到的时候再去调用
  • e.g.
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="password" name="password"/>
                <button>登录</button>
            </form>
        )
    }
}

2、受控组件定义

  • 不使用 ref,会把值存放在state状态中,用的时候直接去状态中取。类似于vue(v-model)和angualr中的双向数据绑定
  • 归纳受控组件的逻辑
    • 可以通过初始state中设置表单的默认值;
    • 每当表单的值发生变化时,调用onChange事件处理器;
    • 事件处理器通过事件对象e拿到改变后的输入值,并更新应用的state
    • setUserName触发视图的重新渲染,完成表单组件值得更新
  • e.g.
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="password" name="password"/>
                <button>登录</button>
            </form>
        )
    }
}

3、函数柯里化

  • 在上一部分中写的登录组件里,为了接收用户名和密码写了两个函数,我们可以将其合并为一个saveFormData函数,接收usernamepassword作为参数来判断输入的是用户名还是密码
  • 但是这样的话,以用户名为例,input就要写成这样:
    • <input onChange={this.saveUsername('username')} type="text" name="username"/>
  • saveUsername会先执行一次返回一个undefinedonChange,导致无法监听事件
  • 这时,可以采用柯里化的方法,设置saveFormData的返回值为一个函数
  • js小知识点:
    const a = 'b'
    b = {a: '1'} // 得到 {a: 1}
    c = {[a]: '2'} // 得到 {b: 2}
    
  • 高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
    • 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
    • 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
    • 常见的高阶函数有:PromisesetTimeoutarr.map()等等
  • 函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。

4、不用柯里化的写法

class Login extends React.Component{
    //初始化状态
    state = {...}
    //保存表单数据到状态中
    saveFormData = (dataType,event)=>{
        this.setState({[dataType]:event.target.value})
    }
    //表单提交的回调
    handleSubmit = ...
    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="password" name="password"/>
                <button>登录</button>
            </form>
        )
    }
}

三、实践练习例子

  • 已在上一节中列出

四、课后个人总结

  • 受控组件有一点像Vue中的双向数据绑定v-model

五、引用参考