React-学习笔记(3-受控/非受控 组件、简易数据双向绑定的实现,高阶函数及函数柯里化优化数据收集)

文章讲述了React中受控组件和非受控组件的概念,以及如何使用它们处理表单数据。受控组件通过onChange事件实时更新state,而非受控组件则通过ref收集数据。文中还介绍了数据双向绑定的实现,并讨论了使用高阶函数和柯里化来优化数据收集,最后提出了一种不使用柯里化的优化方法。
摘要由CSDN通过智能技术生成

目录

0、关于受控组件和非受控组件

1、非受控组件  

2、受控组件

3、数据双向绑定的简单实现

4、高阶函数及函数的柯里化优化数据收集

(4-1)什么是高阶函数?

(4-2)什么是函数的柯里化?

(4-3)改造用户数据收集方式

 5、再做优化(不使用柯里化函数)


0、关于受控组件和非受控组件

        以表单作为简单例子。

        组价的受控和非受控大概可以理解为:

        用户输入的数据或者是选择的操作实时被监视,并将值实时地更新到 state 中,在需要使用时,可以直接到 state 中获取,就是受控的;

        如果用户输入的数据或各种操作的结果在需要收集时是利用 ref 绑定了元素、通过 refs 的方式来获取的,那就是非受控组件;

        是否受控,大概可以理解为数据是否实时 “受监控”。

        由于非受控组件会使用到 ref ,且可能会使用到很多次,所以多少会存在一些性能上的问题,在数据需要收集的时候,可以多考虑使用受控组件来完成。

1、非受控组件  

const {Component, createRef} = React;

class Form extends Component{
    pw = createRef();
    submitForm = (event)=>{
        // 阻止默认时事件的发生(即表单提交的默认跳转)
        event.preventDefault();
        // 需要用的时候才获取两个输入框中用户输入的内容
        console.log(this.pw.current.value, this.userNameNode.value);
    }
    render(){
        return(
            <div>
                { /* 不填action默认提交到当前地址 */ }
                <form action="" onSubmit={this.submitForm}>
                    { /* 内联回调函数的形式 */ }
                    userName: <input ref={cn =>{ this.userNameNode = cn }} type="text" name="username"/><br/> 
                    { /* React.createRef()的形式 */ }
                    password: <input ref={this.pw} type="password" name="pw" /><br/>
                    <input type="submit" value="submit input"/>    
                </form>
            </div>
        )
    }
}
ReactDOM.render(<Form/>, document.querySelector('#test'));

2、受控组件

const {Component, createRef} = React;

class Form extends Component{
    state = {               // 预设需要收集的字段
        username:'',
        pw:'',
        gender:'woman'      // 设置性别为option的第一个,select默认选中第一个
    }
    render(){
        return(
            <div>
                <form action="" onSubmit={this.submitForm}>
                    userName: <input type="text" name="username" onChange={this.unChange}/><br/> 
                    password: <input type="password" name="pw" onChange={this.pwChange}/><br/>
                    gender: <select name="gender" onChange={this.changeGender}>
                        <option value="woman">woman</option>    
                        <option value="man">man</option>  
                    </select><br/>
                    {
                        // 使用默认的reset清除表单内容
                        // <input type="reset" value="reset"/>
                    }
                    <button onClick={this.resetForm}>reset Form</button>
                    <input type="submit" value="submit input"/>    
                </form>
            </div>
        )
    }
    submitForm = (event)=>{
        // 阻止默认时事件的发生(即表单提交的默认跳转)
        event.preventDefault();
        // 需要使用时,直接在state中拿备份存储好的数据,不需要再使用ref绑定的形式
        console.log(this.state, this.state.gender);
    }
    // 实时更新state中的内容
    unChange = (event)=>{
        this.setState({ username:event.target.value });
    }
    pwChange = (e) =>{
        this.setState({ pw:e.target.value });
    }
    changeGender = (e)=>{
        this.setState({ gender:e.target.value });
    }
}
ReactDOM.render(<Form/>, document.querySelector('#test'));

3、数据双向绑定的简单实现

const {Component, createRef} = React;

class Form extends Component{
    state = {
        value:0
    }
    render(){
        return(
            <div>
                { /* label 标签中的for 要改写成 htmlFor,其值对应着指定输入框的id */ }
                <label htmlFor="inpnum">
                    请输入一个不大于10的数
                    { /* 
                        value 绑定 state 中的value,
                        onChange 绑定一个自定义方法,监视用户的输入
                        当用户有输入时,state中的value会实时更新 (用户触发)
                        当用户输入的数大于 10 时,系统自动重置为0 (系统触发)
                    */ }
                    <input type="text" id="inpnum" value={this.state.value} onChange={this.numberChange}/>
                </label>
            </div>
        )
    }
    numberChange = (e)=>{
        if(e.target.value > 10){
            this.setState({ value:0 });
            return;
        }
        // 少了以下这句,用户无法在输入框进行输入
        this.setState({ value:e.target.value });
    }
}
ReactDOM.render(<Form/>, document.querySelector('#test'));

4、高阶函数及函数的柯里化优化数据收集

(4-1)什么是高阶函数?

        简答:满足以下条件之一的函数可以被称为是高阶函数:

        ① 该函数接收另外的函数作为自己的参数;

        ② 该函数返回的内容是一个函数;

常见的高阶函数举例:setTimeout、Promise、Array.map、Array.filter ......

(4-2)什么是函数的柯里化?

        简答:把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数

函数的柯里化举例:

        将三个数值参数相加作为返回值的函数的普通写法:

        (控制台换行输入:Shift + Enter)

        

        函数柯里化改造:

等价于:

(4-3)改造用户数据收集方式

         为每一项用于收集用户数据的标签都添加一个 onChange 事件,为他们都绑定一个函数updateValue,这个函数加上小括号,把当前标签所收集的用户数据名称作为参数传递过去。

        这样,在 React 初次渲染该组件的时候,遇到这些标签都会执行一遍这个函数,并传入数据项名称。

        这个函数会返回一个匿名的函数给这样的每一个标签的 onClick 事件作为回调执行,所以这个匿名的函数会收到一个默认的参数,即事件对象。

        有了事件对象,而且这个事件对象就是触发 onClick 事件的源,那就可以直接获取到更新后的新状态(值)。同时,我们也拿到了当前项的数据名称(每一个匿名的回调函数里面都有一个数据:type,表示当前项对应的数据名称,如 userName),所以就可以利用 setState 去更新当前数据名称所对应的值了。

        以第一项(收集userName,数据项名称为userName)为例,也可以理解为 onChange 事件触发时,会调用函数 this.updateValue('userName')(eventObj) 即 (this.updateValue('userName'))(eventObj)。

        这样,只需要一个更具有普遍性的高阶函数,就能完成对表单众多数据的收集和更新了。

const {Component, createRef} = React;

class Form extends Component{
    state = {
        userName:'',
        oldPassword:'',
        newPassword:'',
        checkCode:''
    }
    render(){
        return(
            <div>
                userName: <input type="text" onChange={this.updateValue('userName')}/><br/>
                oldPassword: <input type="password" onChange={this.updateValue('oldPassword')}/><br/>
                newPassword: <input type="password" onChange={this.updateValue('newPassword')}/><br/>
                checkCode: <input type="text" onChange={this.updateValue('checkCode')}/><br/>
                <input type="submit" value="submit"/>
            </div>
        )
    }
    // 每一个数据项在渲染时都会调用这个方法,把该方法返回的函数赋给 onChange
    // 在数据项的内容被更新时,会调用这个返回的函数
    // updateValue 接收到的参数是调用该方法时传递过来的参数
    updateValue(type){
        // 里面这个返回的函数是供 onChange 调用的,接收到的参数是 event 事件对象
        return (event)=>{
            this.setState({
                // 当拥有键名的时候,更新键所对应的值的方法 [keyName]:newval
                [type]:event.target.value
            })
        }
    }
}
ReactDOM.render(<Form/>, document.querySelector('#test'));

 5、再做优化(不使用柯里化函数)

         写成回调函数的形式,该回调函数再调用指定的函数。

const {Component, createRef} = React;

class Form extends Component{
    state = {
        userName:'',
        oldPassword:'',
        newPassword:'',
        checkCode:''
    }
    render(){
        return(
            <div>
                {
                    // 在花括号中 将一个匿名函数赋给 onChange 事件作为回调
                    // 该匿名函数由 onChange 调用,会收到事件对象作为参数
                    // 该匿名函数中,再调用一个指定的函数,并将当前数据项名称和事件对象作为参数
                    // 更新当前数据项中的值的任务由该制定的函数完成
                }
                userName: <input type="text" onChange={ (event)=>{this.updateValue('userName', event)} }/><br/>
                oldPassword: <input type="password" onChange={ (event)=>{this.updateValue('oldPassword', event)} }/><br/>
                newPassword: <input type="password" onChange={ (event)=>{this.updateValue('newPassword', event)} }/><br/>
                checkCode: <input type="text" onChange={ (event)=>{this.updateValue('checkCode', event)} }/><br/>
                <input type="submit" value="submit"/>
            </div>
        )
    }
    updateValue(type, event){
        this.setState({
            [type]:event.target.value
        })
    }
}
ReactDOM.render(<Form/>, document.querySelector('#test'));

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bodyHealthy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值