You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.7 KiB

统一Form组件使用指南

概述

统一Form组件基于 react-hook-form + zod 验证,提供了一套完整的表单解决方案,包括:

  • 类型安全的表单验证
  • 统一的UI样式
  • 丰富的表单控件
  • 错误处理和状态管理

基础用法

1. 定义Schema

// schemas/example.ts
import { z } from 'zod';
import { formValidations } from '@/lib/form-utils';

export const exampleSchema = z.object({
  name: formValidations.name(50),
  email: formValidations.email(),
  description: formValidations.optional(formValidations.text(0, 200)),
  color: z.string().min(1, '请选择颜色'),
});

export type ExampleFormData = z.infer<typeof exampleSchema>;

2. 使用Form组件

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form } from '@/components/ui/form';
import { FormInput, FormTextarea, FormColorPicker } from '@/components/ui/form-controls';
import { exampleSchema, type ExampleFormData } from '@/schemas/example';
import { defaultColorOptions, createFormSubmitHandler } from '@/lib/form-utils';

function ExampleForm() {
  const form = useForm<ExampleFormData>({
    resolver: zodResolver(exampleSchema),
    defaultValues: {
      name: '',
      email: '',
      description: '',
      color: '#3B82F6',
    },
  });

  const submitHandler = createFormSubmitHandler<ExampleFormData>(
    async (data) => {
      // 处理表单提交
      console.log('提交数据:', data);
    },
    {
      onError: (error) => {
        console.error('提交失败:', error);
      }
    }
  );

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(submitHandler)} className="space-y-4">
        <FormInput
          control={form.control}
          name="name"
          label="名称"
          placeholder="请输入名称"
          required
        />

        <FormInput
          control={form.control}
          name="email"
          label="邮箱"
          type="email"
          placeholder="请输入邮箱"
          required
        />

        <FormTextarea
          control={form.control}
          name="description"
          label="描述"
          placeholder="请输入描述"
          rows={3}
        />

        <FormColorPicker
          control={form.control}
          name="color"
          label="颜色"
          colors={defaultColorOptions}
        />

        <Button type="submit" disabled={form.formState.isSubmitting}>
          {form.formState.isSubmitting ? '提交中...' : '提交'}
        </Button>
      </form>
    </Form>
  );
}

可用的表单控件

FormInput

文本输入框,支持多种类型:

  • type: 'text' | 'email' | 'password' | 'number'

FormTextarea

多行文本框:

  • rows: 行数,默认3行

FormSelect

下拉选择框:

  • options: SelectOption[] 选项数组

FormColorPicker

颜色选择器:

  • colors: ColorOption[] 颜色选项数组

FormInfo

只读信息显示:

  • label: 标签
  • value: 显示值
  • description: 可选描述

验证规则

使用 formValidations 工具函数:

import { formValidations } from '@/lib/form-utils';

const schema = z.object({
  // 必填字段
  required: formValidations.required('此字段必填'),

  // 文本长度限制
  text: formValidations.text(0, 100, '内容'),

  // 名称验证(文件夹/项目名)
  name: formValidations.name(50),

  // 邮箱验证
  email: formValidations.email(),

  // 密码验证
  password: formValidations.password(8),

  // URL验证
  url: formValidations.url(),

  // 数字验证
  number: formValidations.number(0, 100),

  // 可选字段
  optional: formValidations.optional(formValidations.text(0, 200)),
});

表单提交处理

使用 createFormSubmitHandler 创建提交处理器:

const submitHandler = createFormSubmitHandler<FormData>(
  async (data) => {
    // API调用
    await api.create(data);
  },
  {
    onSuccess: (data) => {
      // 成功回调
      console.log('创建成功:', data);
    },
    onError: (error) => {
      // 错误处理
      console.error('创建失败:', error);
    },
  }
);

最佳实践

  1. Schema定义: 将表单Schema定义在独立的文件中,便于复用和维护
  2. 类型安全: 使用TypeScript类型推断,确保类型安全
  3. 错误处理: 统一使用 createFormSubmitHandler 处理表单提交
  4. 验证规则: 优先使用 formValidations 中的预定义规则
  5. 默认值: 总是为表单字段提供合理的默认值
  6. 禁用状态: 在提交过程中禁用表单控件,防止重复提交

示例项目

参考 CreateFolderModal 组件的实现,了解完整的使用方式。