Yup表单验证核心原理与项目中的踩坑经验分享

德超的笔记 交互 阅读 2,566
赞 107 收藏
二维码
手机扫码查看
反馈

先看效果,再看代码

最近在做一个表单校验的需求,本来想自己写一堆if-else来判断,但后来发现Yup这个库简直是神器。直接上个简单例子:

Yup表单验证核心原理与项目中的踩坑经验分享

import * as Yup from 'yup';

const schema = Yup.object().shape({
  name: Yup.string().required("名字不能为空").min(2, "名字太短了"),
  age: Yup.number().required("年龄必填").positive("年龄不能是负数").integer("年龄必须是整数")
});

schema.validate({ name: "张", age: -5 })
  .catch(err => console.log(err.errors)); 
// 输出:["名字太短了", "年龄不能是负数"]

上面这段代码亲测有效,几行就搞定了复杂的校验逻辑。

这个场景最好用

我最常用Yup的场景就是配合React Hook Form做表单校验。两者结合使用简直不要太爽:

import { useForm } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';

const schema = Yup.object().shape({
  email: Yup.string().email("邮箱格式不对").required("邮箱必填"),
  password: Yup.string().min(6, "密码至少6位").required("密码必填")
});

function App() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: yupResolver(schema)
  });

  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("email")} />
      {errors.email && <p>{errors.email.message}</p>}
      
      <input type="password" {...register("password")} />
      {errors.password && <p>{errors.password.message}</p>}
      
      <button type="submit">提交</button>
    </form>
  );
}

这种方式我用了好几个项目,建议直接用这种方式,省心省力。

踩坑提醒:这三点一定注意

虽然Yup很好用,但我在这几个地方踩过坑,给大家提个醒:

  • 异步校验顺序问题:如果你用了test方法做自定义校验,记得要return一个Promise,不然校验结果可能会乱序。
  • 类型转换陷阱:Yup会在校验前自动转换数据类型,比如字符串”123″会被转成数字123,这点要注意。
  • 嵌套对象校验:处理深层嵌套对象时,.shape()里面还要继续写.shape(),别忘了每个层级都要定义。

一些高级用法和技巧

除了基本校验,Yup还有一些很实用的高级功能:

// 动态校验规则
const dynamicSchema = Yup.object().shape({
  password: Yup.string().required(),
  confirmPassword: Yup.string()
    .oneOf([Yup.ref('password'), null], "两次密码不一致")
});

// 自定义校验
const customSchema = Yup.object().shape({
  username: Yup.string()
    .test(
      "unique-username",
      "用户名已存在",
      async (value) => {
        const response = await fetch(https://jztheme.com/api/checkUsername?name=${value});
        const data = await response.json();
        return !data.exists;
      }
    )
});

这里特别要说下自定义校验,刚开始我总是忘记加async/await,折腾了半天才发现问题出在这。

说点别的

其实Yup还能和很多其他库搭配使用,比如Formik、Redux Form之类的。不过我个人更喜欢React Hook Form,轻量又灵活。对了,Yup现在也支持TypeScript了,类型提示很友好。

以上是我个人对Yup的完整讲解,有更优的实现方式欢迎评论区交流。这个技术的拓展用法还有很多,后续会继续分享这类博客。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论