Formik是一个专为React构建的开源表单库。它提供了一个易于使用的API来处理表单状态管理,表单验证以及表单提交。Formik支持React中的所有表单元素和事件,可以很好地与React生态系统中的其他库集成。同时,Formik还提供了一些高级功能,如支持异步验证、字段级别的验证、根据表单状态变化自动计算属性等。
Formik的优势,相较于传统的表单处理方法,Formik具有以下优势:
1、Formik安装,使用npm或yarn安装Formik。在终端中,切换项目目录并运行此命令 npm install formik
或 yarn add formik
。
2、表单数据绑定以及提交处理
useFormik HOOK 参数说明:
onSubmit 属性定义了一个回调函数,在表单提交时被调用。在回调函数中可以访问表单中所有输入框的值并执行提交操作,通过 setSubmitting 函数,可以设置表单的提交状态。在表单的渲染函数中通过 handleSubmit 属性来处理表单的提交,使用 isSubmitting(默认false) 属性来禁用提交按钮,直到表单提交完成。
const formik = useFormik({
initialValues: {
username: '',
password: ''
},
onSubmit: (values, {setSubmitting}) => {
// formik 已经默认帮我们阻止了默认执行
console.log('values: ', values);
setSubmitting(true)
}
})
……
useFormik 返回对象属性解释:
、
、 或
的更改处理程序如果没有 formik,那么就得一个个写change事件。
3、表单校验
Formik 不仅跟踪表单values,还跟踪其验证和错误消息。要使用 JS 添加验证,需指定一个自定义验证函数并将其传递给钩子 useFormik()
的参数 validate。如果存在错误,这个自定义验证函数应该生成一个匹配的error对象。
validate: values => {
const errors = {}
if (!values.username) {
errors.username = '请输入用户名'
} else if (values.username.length < 6 || values.username.length > 16) {
errors.username = '请输入6~16位的用户名'
} else if (!/^\w{6,16}$/.test(values.username)) {
errors.username = '请输入由字母、数字、下划线组成的用户名'
}
if (!values.password) {
errors.password = '请输入密码'
} else if (values.password.length < 6 || values.password.length > 16) {
errors.password = '请输入6~16位的密码'
} else if (!/^\w{6,16}$/.test(values.password)) {
errors.password = '请输入由字母、数字、下划线组成的密码'
}
console.log('errors: ', errors);
return errors
}
默认情况下,Formik 将在每次击键(onChange)事件以及提交之前进行验证。传递 formik.handleBlur
给输入元素的 onBlur
属性,那么会在输入元素的失焦(onBlur)事件中进行验证:
校验确实实现了,但是如果希望在提交表单的时候再显示错误,需要怎么做呢?
Formik 会跟踪哪些字段已被访问过。它将这些信息存储在一个名为 touched 的对象中,这些值为boolean值。
{formik.touched.username && formik.errors.username ? formik.errors.username : ''}
Yup是一个构建对象模式的JavaScript模式验证器,用于验证和解析数据。它提供了一种声明式方法来创建校验模式。
由于 Formik 作者/用户非常喜欢Yup,因此 Formik 有一个名为 Yup 的特殊配置道具validationSchema,它会自动将 Yup 的验证错误消息转换为一对象。
1、Yup 安装 npm install yup
或 yarn add yup
2、使用 Yup 校验表单:
validationSchema={Yup.object({...})}
,使用 validationSchema 和 Yup 搭配之后就不需要再使用validate配置了。 validationSchema: Yup.object({
username: Yup.string().required('请输入用户名')
.min(6, '请输入6~16位的用户名')
.max(16, '请输入6~16位的用户名')
.matches(/^\w{6,16}$/, '请输入由字母、数字、下划线组成的用户名'),
password: Yup.string().required('请输入密码')
.min(6, '请输入6~16位的密码')
.max(16, '请输入6~16位的密码')
.matches(/^\w{6,16}$/, '请输入由字母、数字、下划线组成的密码')
})
以上都是通过 useFormik 拿到控制formik表单的内容,但是这样不容易形成封装,也就是说无法进行实例传值。而Formik由于配备了React Context,因此Formik本身就可以管理所包裹的JSX。
formik完全遵守React的组件化原则,可以和其他库或自定义逻辑无缝集成:
组件和Context API实现跨组件通信。
、ErrorMessage
等的自定义组件,提高代码复用性和可维护性。 { // 提交表单执行的函数
setTimeout(() => {
console.log('values: ', values);
setSubmitting(true)
}, 2000);
}}
validationSchema={Yup.object({ // 设置表单校验的模式
username: Yup.string().required('请输入用户名')
.min(6, '请输入6~16位的用户名')
.max(16, '请输入6~16位的用户名')
.matches(/^\w{6,16}$/, '请输入由字母、数字、下划线组成的用户名'),
password: Yup.string().required('请输入密码')
.min(6, '请输入6~16位的密码')
.max(16, '请输入6~16位的密码')
.matches(/^\w{6,16}$/, '请输入由字母、数字、下划线组成的密码')
})}
>
{({handleSubmit, values, touched, handleChange, handleBlur, errors, isSubmitting}) => {
return
}}
1、ErrorMessage 捕捉错误的容器,必传一个name属性。
2、Field 将自动将输入连接到 Formik,默认渲染是input输入框,有以下几种方法渲染:
function MyField({field, form}) {
console.log('field: ', field);
console.log('form: ', form);
return
}
……
{ console.log('values: ', values); }} // 提交表单执行的函数
validationSchema={Yup.object({ // 设置表单校验的模式
phone: Yup.string().required('请输入电话号码')
.matches(/^1[0-9]{10}/, '请输入有效的电话号码')
})}
>
{({handleSubmit}) => {
return
}}
Formik 支持嵌套对象和数组:
Yup.object({})
Yup.array().of()
{
console.log('values: ', values)
setSubmitting(true)
}}
validationSchema={Yup.object({
social: Yup.object({
wechat: Yup.string().required('请输入微信'),
qq: Yup.string().required('请输入QQ').matches(/^[\w]$/, '请输入有效的QQ')
}),
frends: Yup.array().of(Yup.string().required('请输入你的朋友'))
})}>
{({values, handleChange, handleBlur, touched, errors, isSubmitting, setValues, setFieldValue, handleSubmit}) => {
console.log('object array values: ', values);
console.log('object array handleChange: ', handleChange);
console.log('object array handleBlur: ', handleBlur);
console.log('object array touched: ', touched);
console.log('object array errors: ', errors);
console.log('object array setValues: ', setValues);
console.log('object array setFieldValue: ', setFieldValue);
return }}