概述
Zod 是一个 TypeScript 优先的模式验证库,提供强大的运行时类型检查和数据验证功能。在 Vue3 项目中集成 Zod,可以显著提升代码的类型安全性和数据验证能力。
主要优势
- 类型安全:编译时和运行时双重类型保护
- 简洁易用:声明式 API,学习成本低
- 功能强大:支持复杂的数据结构和自定义验证规则
- Vue3 友好:与 Composition API 完美结合
安装
npm install zod
# 或
yarn add zod
# 或
pnpm add zod
基础用法
创建验证模式
import { z } from "zod";
// 基础类型验证
const userSchema = z.object({
id: z.number(),
name: z.string().min(1, "姓名不能为空"),
email: z.string().email("邮箱格式不正确"),
age: z.number().min(18, "年龄必须大于18岁").optional(),
isActive: z.boolean().default(true),
});
// 类型推断
type User = z.infer<typeof userSchema>;
数据验证
// 安全解析
const result = userSchema.safeParse({
id: 1,
name: "张三",
email: "zhangsan@example.com",
age: 25,
});
if (result.success) {
console.log("验证成功:", result.data);
} else {
console.log("验证失败:", result.error.issues);
}
// 直接解析(会抛出异常)
try {
const user = userSchema.parse(invalidData);
} catch (error) {
console.error("验证失败:", error);
}
Vue3 组件实践
表单验证组件
<template>
<div
class="min-h-screen bg-gray-50 flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8"
>
<div class="max-w-md w-full space-y-8">
<div>
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
登录
</h2>
</div>
<form @submit.prevent="handleSubmit" class="mt-8 space-y-6">
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1"
>姓名</label
>
<input
v-model="form.name"
type="text"
@input="clearError('name')"
:class="[
'appearance-none rounded-md relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm',
errors.name ? 'border-red-500' : 'border-gray-300',
]"
placeholder="请输入您的姓名"
/>
<span v-if="errors.name" class="mt-1 text-sm text-red-600">{{
errors.name
}}</span>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1"
>邮箱</label
>
<input
v-model="form.email"
type="email"
@input="clearError('email')"
:class="[
'appearance-none rounded-md relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm',
errors.email ? 'border-red-500' : 'border-gray-300',
]"
placeholder="请输入您的邮箱"
/>
<span v-if="errors.email" class="mt-1 text-sm text-red-600">{{
errors.email
}}</span>
</div>
</div>
<div>
<button
type="submit"
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition duration-150 ease-in-out"
>
提交
</button>
</div>
</form>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, reactive } from "vue";
import { z } from "zod";
// 定义验证模式
const userSchema = z.object({
name: z.string().min(1, "姓名不能为空"),
email: z.string().email("邮箱格式不正确"),
});
type UserForm = z.infer<typeof userSchema>;
// 表单数据
const form = reactive<UserForm>({
name: "",
email: "",
});
// 错误信息
const errors = reactive<Partial<Record<keyof UserForm, string>>>({});
// 清除指定字段的错误信息
const clearError = (field: keyof UserForm) => {
if (errors[field]) {
delete errors[field];
}
};
// 验证表单
const validateForm = () => {
const result = userSchema.safeParse(form);
if (!result.success) {
Object.keys(errors).forEach((key) => delete errors[key as keyof UserForm]);
result.error.issues.forEach((issue) => {
if (issue.path[0]) {
errors[issue.path[0] as keyof UserForm] = issue.message;
}
});
return false;
}
Object.keys(errors).forEach((key) => delete errors[key as keyof UserForm]);
return true;
};
// 提交处理
const handleSubmit = () => {
if (validateForm()) {
console.log("表单数据:", form);
alert("表单提交成功!");
} else {
console.log("表单验证失败");
}
};
</script>

高级用法
自定义验证逻辑
const conditionalSchema = z
.object({
type: z.enum(["individual", "company"]),
name: z.string(),
email: z.string().email(),
companyName: z.string().optional(),
})
.refine(
(data) => {
if (data.type === "company" && !data.companyName) {
return false;
}
return true;
},
{
message: "公司类型必须填写公司名称",
path: ["companyName"],
}
);
自定义验证器
const customSchema = z.custom(
(value) => typeof value === "string",
"Expected string, received number"
);
console.log(customSchema.parse("hello")); // hello
console.log(customSchema.parse(123)); // ZodError: Expected string, received number
总结
Zod 在 Vue3 项目中的应用提供了强大的类型安全和数据验证能力。通过合理使用 Zod,可以:
- 提升代码的类型安全性
- 简化表单验证逻辑
- 确保 API 数据的完整性
- 提供更好的开发体验
原文链接:https://code.ifrontend.net/archives/1281,转载请注明出处。
评论0