formik来实现表单校验

表单验证说明

  • 表单提交前,需要先进性表单验证,验证通过后再提交表单
  • 方式一:antd-mobile 组件库的方式(需要InputItem文本输入组件)
  • 推荐:使用更通用的 formik,React中专门用来进行表单处理和表单校验的库

介绍

  • Github地址:formik文档
  • 场景:表单处理,表单验证
  • 优势:轻松处理React中的复杂表单,包括:获取表单元素的值,表单验证和错误信息,处理表单提交,并且将这些内容放在一起统一处理,有利于代码阅读,重构,测试等
  • 使用两种方式:1. 高阶组件(withFormik) 2. render-props(<Formik render={() => {}} />)

formik来实现表单校验(★★★)

重构

  • 安装: yarn add formik
  • 导入 withFormik,使用withFormit 高阶组件包裹Login组件
  • 为withFormit提供配置对象: mapPropsToValues / handleSubmit
  • 在Login组件中,通过props获取到values(表单元素值对象),handleSubmit,handleChange
  • 使用values提供的值,设置为表单元素的value,使用handleChange设置为表单元素的onChange
  • 使用handleSubmit设置为表单的onSubmit
  • 在handleSubmit中,通过values获取到表单元素值
  • 在handleSubmit中,完成登录逻辑

// Login组件中
render() {
  // const { username, password } = this.state

  // 通过 props 获取高阶组件传递进来的属性
  const { values, handleSubmit, handleChange } = this.props

  return (
    <div className={styles.root}>
      {/* 顶部导航 */}
      <NavHeader className={styles.navHeader}>账号登录</NavHeader>
      <WhiteSpace size="xl" />

      {/* 登录表单 */}
      <WingBlank>
        <form onSubmit={handleSubmit}>
          <div className={styles.formItem}>
            <input
              className={styles.input}
              value={values.username}
              onChange={handleChange}
              name="username"
              placeholder="请输入账号"
            />
          </div>
          {/* 长度为5到8位,只能出现数字、字母、下划线 */}
          {/* <div className={styles.error}>账号为必填项</div> */}
          <div className={styles.formItem}>
            <input
              className={styles.input}
              value={values.password}
              onChange={handleChange}
              name="password"
              type="password"
              placeholder="请输入密码"
            />
          </div>
          {/* 长度为5到12位,只能出现数字、字母、下划线 */}
          {/* <div className={styles.error}>账号为必填项</div> */}
          <div className={styles.formSubmit}>
            <button className={styles.submit} type="submit">
              登 录
            </button>
          </div>
        </form>
        <Flex className={styles.backHome}>
          <Flex.Item>
            <Link to="/registe">还没有账号,去注册~</Link>
          </Flex.Item>
        </Flex>
      </WingBlank>
    </div>
  )
}

// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
  // 提供状态:
  mapPropsToValues: () => ({ username: '', password: '' }),
  // 表单的提交事件
  handleSubmit: async (values, { props }) => {
    // 获取账号和密码
    const { username, password } = values

    // 发送请求
    const res = await API.post('/user/login', {
      username,
      password
    })

    console.log('登录结果:', res)
    const { status, body, description } = res.data

    if (status === 200) {
      // 登录成功
      localStorage.setItem('hkzf_token', body.token)

      // 注意:无法在该方法中,通过 this 来获取到路由信息
      // 所以,需要通过 第二个对象参数中获取到 props 来使用 props
      props.history.go(-1)
    } else {
      // 登录失败
      Toast.info(description, 2, null, false)
    }
  }
})(Login)

两种表单验证方式

  • 两种方式

    • 通过validate 配置手动校验

  • 通过 validationSchema 配置项配合Yup来校验

  • 推荐: validationSchema配合Yup的方式进行表单校验

给登录功能添加表单验证

  • 安装: yarn add yup (Yup 文档),导入Yup
// 导入Yup
import * as Yup from 'yup'
  • 在 withFormik 中添加配置项 validationSchema,使用 Yup 添加表单校验规则

  • 在 Login 组件中,通过 props 获取到 errors(错误信息)和 touched(是否访问过,注意:需要给表单元素添加 handleBlur 处理失焦点事件才生效!)
  • 在表单元素中通过这两个对象展示表单校验错误信

示例代码:

// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
  ...
  // 添加表单校验规则
  validationSchema: Yup.object().shape({
    username: Yup.string()
      .required('账号为必填项')
      .matches(REG_UNAME, '长度为5到8位,只能出现数字、字母、下划线'),
    password: Yup.string()
      .required('密码为必填项')
      .matches(REG_PWD, '长度为5到12位,只能出现数字、字母、下划线')
  }),
  ...
})(Login)

在结构中需要渲染错误信息:

{/* 登录表单 */}
<WingBlank>
  <form onSubmit={handleSubmit}>
    ...  用户名的错误提示
    {errors.username && touched.username && (
      <div className={styles.error}>{errors.username}</div>
    )}
    ... 密码框的错误提示
    {errors.password && touched.password && (
      <div className={styles.error}>{errors.password}</div>
    )}
    ...
</WingBlank>

简单处理

  • 导入 Form组件,替换form元素,去掉onSubmit

  • 导入Field组件,替换input表单元素,去掉onChange,onBlur,value

  • 导入 ErrorMessage 组件,替换原来的错误消息逻辑代码

  • 去掉所有 props

示例代码:

// 导入withFormik
import { withFormik, Form, Field, ErrorMessage } from 'formik'

<Form>
  {/* 账号 */}
  <div className={styles.formItem}>
    <Field
      className={styles.input}
      name="username"
      placeholder="请输入账号"
    />
  </div>
  <ErrorMessage
    className={styles.error}
    name="username"
    component="div"
  />
  {/* 密码 */}
  <div className={styles.formItem}>
    <Field
      className={styles.input}
      name="password"
      type="password"
      placeholder="请输入密码"
    />
  </div>
  <ErrorMessage
    className={styles.error}
    name="password"
    component="div"
  />
  <div className={styles.formSubmit}>
    <button className={styles.submit} type="submit">
      登 录
    </button>
  </div>
</Form>
posted @ 2020-12-28 22:04  sk-xm  阅读(808)  评论(0编辑  收藏  举报