美文网首页
react高阶组件封装input框校验

react高阶组件封装input框校验

作者: 雨落倾城夏微凉_e861 | 来源:发表于2020-08-05 15:10 被阅读0次

    最近看了很多高阶组件的资料和视频,学到了一些东西,写个input校验框复习一下。

    //我们来创建两个组件,名字随意,一个高阶组件一个展示组件,为了能够使用装饰器展示组件我们使用类组件
    //创建展示组件InputComp
    class InputComp extends React.Component {
        onsubmit = () => {
            
        }
        render(){
            return (
                <div>
                    <div>
                        用户名:<input />
                    </div>
                    <div>
                        密码:<input type="password"/>
                    </div>
                    <button onClick={this.onsubmit}>提交</button>
                </div>
            )
        }
    }
    

    然后我们创建高阶组件,我们希望高阶组件可以完成对所有表单的验证,并且将验证的结果和最终提交的值都返回给我们,以便于我们根据结果和value做下一步的操作,比如注册、登录等操作。
    我们通过高阶组件给展示组件传递一个方法:gradeInput,该方法接收两个参数,一个name值比如:uname,password,phone等,另一个参数是验证内容的数组对象我们可以模仿ant-design放到rules中。这个方法返回一个被我们处理过的input。

    //创建高阶组件
    function CheckInput(Comp){
        return class extends React.Component{
            constructor(props){
                super(props);
                this.obj = {};//定义一个空对象存放验证信息
                this.state = {};//定一个状态保存input值和输入有误时的提示信息
            }
            gradeInput = (name, option) => {
                this.obj[name] = option;//将传过来的对象通过计算属性存入obj
                return Iptcomp => {//gradeInput函数返回一个带参数的函数,我们将<input />输入框作为参数传入,来为他添加属性和方法
                    return (
                        <div>
                            {
                            // 由React.createElement生成的元素不能直接修改,我们需要克隆一份
                                React.cloneElement(Iptcomp, {
                                    name: name,    //给input添加name属性并将传入的name赋给他
                                    value: this.state[name] || "",   //  添加value属性,我们会通过下面的onChange方法将输入的值通过计算属性存到状态中,如果计算属性还不存在则赋予空值,不给默认空值会报警告信息
                                    onChange: this.handleChange  //为input添加方法
                                })
                            }
                            {//如果有提示信息,一样通过计算属性存到状态,如果有的话就展示
                                this.state[name + 'msg'] && <p style={{color: "red"}}>{this.state[name + 'msg']}</p>
                            }
                        </div>
                    )
                }
            }
            handleChange = (e) => {//实现onChange方法我们先打印一下
              this.setState({[e.target.name]: value});//将value存入state中
              console.log(e.target.value,e.target.name)
            }
            render(){
                return(//将gradeInput方法传给要修饰的组件
                    <Comp {...this.props} gradeInput={this.gradeInput} ></Comp>
                )
            }
        }
    }
    

    接着我们修改一下InputComp,并用装饰器装饰

    @CheckInput
    class InputComp extends React.Component {
        onsubmit = () => {
        }
        render(){
            const { gradeInput } = this.props;
            return (
                <div>
                    <div>
                        用户名:{
                            gradeInput("uname",{
                                rules:[{required: true, message: "用户名不能为空"}, {type: "password", reg: /^[a-zA-Z]/, message: "用户名必须以字母开头"}]
                            })(<input />)
                        }
                    </div>
                    <div>
                        密码:{
                            gradeInput("pwd",{
                                rules:[{required: true, message: "密码不能为空"}]
                            })(<input type="password"/>)
                        }
                    </div>
                    <button onClick={this.onsubmit}>提交</button>
                </div>
            )
        }
    }
    export default InputComp
    

    启动项目查看控制台有没有输出name和value

    1.png

    证明我们写的的代码没问题,下面接着完善开始写校验的部分,校验分两块一个是每个input的校验,一个是提交的校验。

    //先修改高阶组件
    function CheckInput(Comp){
        return class extends React.Component{
            constructor(props){
                super(props);
                this.obj = {};
                this.state = {};
            }
            verificateFiled = (name) => {//校验输入框,在handleChange里面调用
                //我们之前把校验信息存入obj的计算属性中,通过遍历去挨个校验
                const isverif = this.obj[name].rules.map(item => {
                    if(item.required){//校验必填项
                        if(this.state[name]){
                            this.setState({[name + "msg"]: ""});//校验成功清空提示信息并返回true否则返回false
                            return true
                        }
                        this.setState({[name + "msg"]: item.message})
                        return false
                    }
                    if(item.reg && this.state[name]){//如果我们有传入正则,则进行正则校验
                        if(item.reg.test(this.state[name])){
                            this.setState({[name + "msg"]: ""})
                            return true
                        }
                        this.setState({[name + "msg"]: item.message})
                        return false
                    }
                })
                //遍历完会返回一个true和false的数组isverif,只要有一个为false则为不通过
                return isverif.indexOf(false) > -1 ? false : true;
            }
            verificateAll = (callback) => {//校验所有input,主要是为了提交时验证,所以我们需要把这个函数传递给展示组件,并给他传入一个函数,方便提交的后续操作
              const ispass = Object.keys(this.obj).map(item => {//取出obj中的key值,当时存储的时候是以传入的name作为key的,将key传给verificateFiled
                    return this.verificateFiled(item);
                })
            //返回的ispass也是一个true和false组成的数组,只要存在false即为校验不通过
            //我们将最终的校验结果,并把state状态中的值传入,便于我们后续提交
                callback(!ispass.includes(false), this.state);
            }
            handleChange = (e) => {
                const {name, value} = e.target;
              //值改变时就开始校验,因为状态的异步更新机制,我们要在setState的回调函数中调用,保障每次拿到的是最新的值
                this.setState({[name]: value}, () => this.verificateFiled(name));
            }
            gradeInput = (name, option) => {
                this.obj[name] = option;
                return Iptcomp => {
                    return (
                        <div>
                            {
                                React.cloneElement(Iptcomp, {
                                    name: name,
                                    value: this.state[name] || "",
                                    onChange: this.handleChange
                                })
                            }
                            {
                                this.state[name + 'msg'] && <p style={{color: "red"}}>{this.state[name + 'msg']}</p>
                            }
                        </div>
                    )
                }
            }
            render(){
                return(//将verificateAll也传给展示组件
                    <Comp {...this.props} gradeInput={this.gradeInput} verificateAll={this.verificateAll}></Comp>
                )
            }
        }
    }
    

    给展示组件添加提交方法

    @CheckInput
    class InputComp extends React.Component {
        //提交方法
        onsubmit = () => {
            this.props.verificateAll((isverify, allVal) => {//我们在高阶组件中为verificateAll的回调函数传入了校验是否成功和state中保存的值
                if(isverify){
                    console.log("校验成功", allVal)
                }else{
                    console.log("请检查输入的内容")
                }
            })
        }
        render(){
            const { gradeInput, onsubmit } = this.props;
            return (
                <div>
                    <div>
                        用户名:{
                            gradeInput("uname",{
                                rules:[{required: true, message: "用户名不能为空"}, {type: "password", reg: /^[a-zA-Z]/, message: "用户名必须以字母开头"}]
                            })(<input />)
                        }
                    </div>
                    <div>
                        密码:{
                            gradeInput("pwd",{
                                rules:[{required: true, message: "密码不能为空"}]
                            })(<input type="password"/>)
                        }
                    </div>
                    <button onClick={this.onsubmit}>提交</button>
                </div>
            )
        }
    }
    
    export default InputComp
    

    这样便实现了input校验的封装,我们下来检测一下是否可以正常校验。


    2.png

    可以看到,当我们输入不符合要求时,校验信息是正确的,点击提交控制台也有正确的提示。
    下来,我们正确输入后点击按钮看是否正常输出input的值


    3.png

    相关文章

      网友评论

          本文标题:react高阶组件封装input框校验

          本文链接:https://www.haomeiwen.com/subject/momnrktx.html