我的react开发笔记 - 基于antd的表单验证 以及 JavaScript中Promise对象的相关总结
无论是react还是vue,表单在提交之前都需要对其中的输入进行验证,比如判断必填项是否填写或者输入是否符合规范。因为本文使用基于react的界面库antd进行开发,因此在这里记录一下antd进行form验证的简单方法。
-- By Brisk yu
场景:在登录页面有两个输入框,分别获取用户的用户名和密码,如下所示:
从图中可以看出,该form包含三个item,分别是两个input和一个button。显然,该场景下需要进行输入校验的是两个input。
首先添加一个简单的校验规则:账号和密码是必填项,如果没有填写就给予提示。
一 当input内容改变时进行校验
通过在对应的item中添加rules属性来实现,对应代码如下:
<Form.Item label="账号" name="userId" rules={[{ required: true, message: '请输入账号' }]}> <Input /> </Form.Item> <Form.Item label="密码" name="password" rules={[{ required: true, message: '请输入密码' }]}> <Input.Password /> </Form.Item>
这样此时当input中内容改变时便会触发校验。rules中规定的校验规则,这里只简单的判断是否填写,后续也可以添加自定义校验规则。如果没有填写,则输出messsage中的内容。
二 点击“登录”按钮时验证
当点击“登录”按钮时同样需要对表单进行验证,只有验证通过了才能继续进行后续操作,比如与后台交互。这里需要用到Form的validateFields方法。
1)通过useRef这个Hook定义一个Ref。在react中,ref就类似于DOM的id。虽然react和vue都不建议直接对DOM进行操作(建议通过数据响应改变DOM),但是在一些情况下仍然需要操作DOM,这时候就可以通过ref来获取DOM。注:函数组件中不支持通过字符串获取ref,需要通过useRef。如下代码所示:
const loginFormRef = useRef(null);
这样就创建了一个ref对象。其中初始值为null
2)在form中引用介个ref,代码如下:
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} size='large' name="login" onValuesChange={onValuesChange} ref={loginFormRef}>
3)这样就可以通过loginFormRef的current属性来调用form的validateFields方法来对表单进行验证。该方法是一个异步promise,代码如下:
loginFormRef.current.validateFields().then(v => { console.log(v) }).catch(errorInfo => { console.log(errorInfo) })
这样就可以在then和catch中分别对验证成功和失败的后续代码进行编写了。
以上就是基于antd实现简单的form验证,该方法可以在input内容改变和提交表单时分别进行验证。
附录 JavaScript中Promise的用法
本文的第二部分介绍了如何在点击“登录”按钮时进行表单的验证,即调用Form Instance的validateFields。值得注意的是,这里的validateFields看似是一个方法,其实是表单ref中的Promise对象。这里简单地总结一下和Promise相关的知识点。
1 什么是Promise
可以将Promise理解为是一个为了处理异步事务而设计的JS中的对象。
2 怎么用Promise
简单来说,当我们拥有了一个Promise对象,就可以通过链式then和catch来分别定义异步事件“成功”与“失败”时所执行的代码(具体来说,这牵扯到Promise构建时的resolve和reject,这里暂且不表)。如同上述的代码:
loginFormRef.current.validateFields().then(v => { console.log(v) }).catch(errorInfo => { console.log(errorInfo) })
上述代码中,当表单检验成功时,执行then中的代码;当表单校验失败时,执行catch中的代码。这里v和errorInfo的具体定义需要参考该Promise对象相关构建代码。在ant design中,这两个变量分表代表了检验成功或失败时的相关信息。
3 如果用类似同步代码的书写方式写Promise
至此,我们已经知道可以通过then catch这种链式写法来使用Promise。但是这里存在一个弊端,即如果then中的内容也是一个Promise,就会形成类似“回调地狱”,使代码难以理解和复用。
因此,需要一种方式,可以让我们以同步代码的书写方式编写Promise。这里涉及的知识点是 await。
简单来说,我们在调用Promise的代码行前添加await,并且将then中的代码直接转移到后续代码行执行;对于catch中的代码,我们用try catch语句将所有代码包裹起来,然后将其挪到新的catch中。如下所示:
try { let v = await loginFormRef.current.validateFields() console.log(v) } catch (errorInfo) { console.log(errorInfo) }
这样,代码就会在await处等待异步任务执行完之后再进行。通过这种编码方式,增强代码的可读性和可移植性。值得一提的是,含有await的方法必须是async的。