跳转到内容

Next.js Zod验证

来自代码酷

Next.js Zod验证[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

Zod是一个TypeScript优先的验证库,用于构建和验证数据结构。在Next.js中,Zod常与表单处理结合使用,以确保用户输入的数据符合预期格式。通过Zod验证,开发者可以轻松定义数据模式(schema),并在客户端或服务器端验证输入数据,减少错误并提高应用程序的可靠性。

Zod的主要特点包括:

  • **类型安全**:与TypeScript深度集成,提供编译时类型检查。
  • **简洁的API**:易于定义复杂的验证规则。
  • **可组合性**:支持嵌套结构和联合类型。
  • **错误处理**:提供清晰的错误信息,便于调试。

安装与基本用法[编辑 | 编辑源代码]

在Next.js项目中使用Zod前,需先安装依赖:

npm install zod

以下是一个简单的Zod验证示例,定义一个用户注册表单的验证规则:

import { z } from 'zod';

// 定义验证模式
const userSchema = z.object({
  username: z.string().min(3, "用户名至少3个字符"),
  email: z.string().email("请输入有效的邮箱地址"),
  age: z.number().min(18, "年龄必须大于18岁").optional(),
});

// 验证数据
const input = {
  username: "alice",
  email: "alice@example.com",
  age: 20,
};

const result = userSchema.safeParse(input);

if (result.success) {
  console.log("验证成功:", result.data);
} else {
  console.error("验证失败:", result.error.errors);
}
    • 输出:**
验证成功: {
  username: "alice",
  email: "alice@example.com",
  age: 20
}

如果输入数据无效(如`username`为"ab"),则会输出错误信息:

验证失败: [
  {
    "code": "too_small",
    "path": ["username"],
    "message": "用户名至少3个字符"
  }
]

与Next.js表单集成[编辑 | 编辑源代码]

在Next.js中,Zod通常与React Hook Form结合使用,实现客户端和服务端双重验证。以下是一个完整的表单处理示例:

客户端验证[编辑 | 编辑源代码]

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const schema = z.object({
  name: z.string().min(1, "姓名不能为空"),
  password: z.string().min(8, "密码至少8位"),
});

type FormData = z.infer<typeof schema>;

export default function Form() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>({
    resolver: zodResolver(schema),
  });

  const onSubmit = (data: FormData) => {
    console.log("提交数据:", data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("name")} placeholder="姓名" />
      {errors.name && <p>{errors.name.message}</p>}

      <input {...register("password")} type="password" placeholder="密码" />
      {errors.password && <p>{errors.password.message}</p>}

      <button type="submit">提交</button>
    </form>
  );
}

服务端验证[编辑 | 编辑源代码]

在API路由中验证数据:

import { NextApiRequest, NextApiResponse } from 'next';
import { z } from 'zod';

const schema = z.object({
  productId: z.string().uuid(),
  quantity: z.number().int().positive(),
});

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const result = schema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({ errors: result.error.errors });
  }
  // 处理有效数据...
}

高级特性[编辑 | 编辑源代码]

自定义验证[编辑 | 编辑源代码]

Zod允许通过`.refine()`方法定义自定义规则:

const passwordSchema = z.string()
  .min(8)
  .refine((val) => /[A-Z]/.test(val), "必须包含大写字母");

转换输入数据[编辑 | 编辑源代码]

Zod可在验证时转换数据:

const numberSchema = z.string().transform((val) => parseInt(val));
const result = numberSchema.parse("123"); // 输出: 123 (number类型)

联合类型[编辑 | 编辑源代码]

支持多种可能的类型:

const idSchema = z.union([
  z.string().uuid(),
  z.number().int().positive(),
]);

实际案例:用户注册系统[编辑 | 编辑源代码]

以下是一个完整的用户注册流程,结合Next.js API路由和Zod验证:

1. **前端表单**(使用React Hook Form + Zod) 2. **API路由验证** 3. **数据库存储**

sequenceDiagram participant 前端 participant API路由 participant 数据库 前端->>API路由: 提交表单数据 API路由->>API路由: Zod验证 alt 验证成功 API路由->>数据库: 存储用户数据 数据库-->>API路由: 成功响应 API路由-->>前端: 注册成功 else 验证失败 API路由-->>前端: 错误详情 end

代码实现[编辑 | 编辑源代码]

    • 前端组件**:
// pages/register.tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  terms: z.literal(true),
});

export default function Register() {
  const { register, handleSubmit } = useForm({
    resolver: zodResolver(schema),
  });

  const onSubmit = async (data) => {
    const response = await fetch('/api/register', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    // 处理响应...
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* 表单字段 */}
    </form>
  );
}
    • API路由**:
// pages/api/register.ts
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  terms: z.boolean(),
});

export default async function handler(req, res) {
  const result = schema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json(result.error);
  }
  // 保存到数据库...
  return res.status(201).json({ success: true });
}

最佳实践[编辑 | 编辑源代码]

1. **复用模式**:将常用模式提取为共享模块 2. **渐进式验证**:先验证基本类型,再添加复杂规则 3. **错误处理**:为用户提供清晰的错误信息 4. **性能优化**:在客户端预验证,减少不必要的服务器请求

常见问题[编辑 | 编辑源代码]

如何处理嵌套对象?[编辑 | 编辑源代码]

使用`.object()`嵌套:

const addressSchema = z.object({
  street: z.string(),
  city: z.string(),
});

const userSchema = z.object({
  name: z.string(),
  address: addressSchema,
});

如何验证数组?[编辑 | 编辑源代码]

使用`.array()`:

const tagsSchema = z.array(z.string().min(2)).max(5);

如何设置可选字段?[编辑 | 编辑源代码]

使用`.optional()`:

z.object({
  name: z.string(),
  bio: z.string().optional(),
});

总结[编辑 | 编辑源代码]

Zod为Next.js应用提供了强大的数据验证能力,通过与TypeScript的深度集成,开发者可以在编译时和运行时都获得类型安全保证。结合React Hook Form或直接用于API路由验证,Zod能够显著提高表单处理的可靠性和开发效率。