概述
在前端开发中,表单是用户交互的核心,但同时也是最容易出错的部分。字段名拼写错误、字段类型不一致、数据验证缺失,都会导致运行时错误、难以维护的代码,甚至安全隐患。
随着应用变得复杂,需要一种方式:
- 能 从定义到提交全链路保证字段类型的一致性
- 能让 TS 类型系统真正参与到表单开发的每一层
- 能减少手动维护冗余类型,提高开发效率和可维护性
在本文中,我们通过 vue3 实现一个类型安全的 Form
创建 vue3 项目
通过 pnpm
创建一个 vue3
的 repo
bash
pnpm create vue@latest

如何构建表单
使用 @vee-validate/zod
bash
pnpm install vee-validate @vee-validate/zod
小试牛刀
App.js
<script setup>
import { useForm } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import { z } from 'zod';
const { handleSubmit, defineField, isSubmitting, errors, meta, setFieldError } = useForm({
validationSchema: toTypedSchema(z.object({
name: z.string(),
age: z.number().min(1),
})),
});
const [name, nameAttrs] = defineField('name');
const [age, ageAttrs] = defineField('age');
const onSubmit = handleSubmit(async (values) => {
console.log('Submitting...');
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('Done!', values);
});
</script>
<template>
<form @submit="onSubmit">
<div>
<label for="name">Name:</label>
<input v-model="name" v-bind="nameAttrs" @input="() => setFieldError('name', '')" />
<span>{{ errors.name }}</span>
</div>
<div>
<label for="age">Age:</label>
<input v-model="age" v-bind="ageAttrs" type="number" @input="() => setFieldError('age', '')" />
<span>{{ errors.age }}</span>
</div>
<button :disabled="isSubmitting">
{{ isSubmitting ? 'Submitting...' : 'Submit' }}
</button>
<pre>{{ meta }}</pre>
</form>
</template>