Использование библиотеки Valibot в Nuxt 3 с формой UForm из @nuxt/ui

от автора

в
Время чтения: 3 мин.

В современной веб-разработке валидация форм является критически важной частью пользовательского опыта. В этой статье я покажу, как интегрировать мощную библиотеку валидации Valibot с формами UForm из модуля @nuxt/ui в Nuxt 3.

Что такое Valibot?

Valibot — это легковесная библиотека для валидации данных с TypeScript-first подходом. Она предлагает:

  • Отличную производительность
  • Полную TypeScript-поддержку
  • Гибкость и модульность
  • Простоту использования

Установка необходимых зависимостей

Сначала установим необходимые пакеты:

npm install valibot
# или
yarn add valibot

Модуль @nuxt/ui уже должен быть установлен в вашем проекте Nuxt 3.

Создание схемы валидации с Valibot

Создадим файл schemas/contact.ts для хранения наших схем валидации:

import { string, minLength, email, object, type Output } from 'valibot';

// Схема для контактной формы
export const ContactSchema = object({
  name: string([minLength(2, 'Имя должно содержать минимум 2 символа')]),
  email: string([email('Введите корректный email адрес')]),
  message: string([minLength(10, 'Сообщение должно содержать минимум 10 символов')]),
});

// Тип для TypeScript на основе схемы
export type ContactFormData = Output<typeof ContactSchema>;

Создание компонента формы

Теперь создадим компонент формы в components/ContactForm.vue:

<script setup lang="ts">
import { validate } from 'valibot';
import { ContactSchema, type ContactFormData } from '~/schemas/contact';

const state = reactive({
  name: '',
  email: '',
  message: '',
  errors: {} as Record<string, string>,
});

const isLoading = ref(false);

async function onSubmit() {
  // Очищаем предыдущие ошибки
  state.errors = {};

  try {
    // Валидируем данные с помощью Valibot
    const result = validate(ContactSchema, state);

    // Если валидация прошла успешно, обрабатываем форму
    isLoading.value = true;

    // Здесь может быть вызов API или другая логика обработки
    console.log('Форма отправлена:', result);

    // Сброс формы после успешной отправки
    state.name = '';
    state.email = '';
    state.message = '';

    // Показываем уведомление об успехе
    useToast().add({ title: 'Форма отправлена успешно!' });

  } catch (error) {
    // Обрабатываем ошибки валидации
    if (error instanceof Error) {
      const fieldErrors = JSON.parse(error.message);
      for (const error of fieldErrors) {
        state.errors[error.path[0].key] = error.message;
      }
    }
  } finally {
    isLoading.value = false;
  }
}
</script>

<template>
  <UForm :state="state" @submit="onSubmit">
    <UFormGroup label="Имя" name="name" :error="state.errors.name">
      <UInput v-model="state.name" />
    </UFormGroup>

    <UFormGroup label="Email" name="email" :error="state.errors.email" class="mt-4">
      <UInput v-model="state.email" type="email" />
    </UFormGroup>

    <UFormGroup label="Сообщение" name="message" :error="state.errors.message" class="mt-4">
      <UTextarea v-model="state.message" />
    </UFormGroup>

    <UButton type="submit" class="mt-4" :loading="isLoading">
      Отправить
    </UButton>
  </UForm>
</template>

Альтернативный подход: Композиция useValidate

Для более удобного повторного использования можно создать композицию useValidate:

// composables/useValidate.ts
import { validate, type BaseSchema } from 'valibot';

export function useValidate<T extends BaseSchema>(schema: T) {
  const errors = ref<Record<string, string>>({});

  const validateForm = (data: any) => {
    try {
      errors.value = {};
      const result = validate(schema, data);
      return { valid: true, data: result };
    } catch (error) {
      if (error instanceof Error) {
        const fieldErrors = JSON.parse(error.message);
        for (const err of fieldErrors) {
          errors.value[err.path[0].key] = err.message;
        }
      }
      return { valid: false, errors: errors.value };
    }
  };

  return { errors, validateForm };
}

Теперь можно упростить наш компонент формы:

<script setup lang="ts">
import { ContactSchema } from '~/schemas/contact';

const { errors, validateForm } = useValidate(ContactSchema);

const state = reactive({
  name: '',
  email: '',
  message: '',
});

async function onSubmit() {
  const { valid } = validateForm(state);
  if (!valid) return;

  // Логика отправки формы...
}
</script>

Преимущества такого подхода

  1. Типобезопасность: TypeScript подсказывает типы полей формы
  2. Переиспользование: Схемы валидации можно использовать на фронтенде и бэкенде
  3. Производительность: Valibot очень легковесен
  4. Интеграция: Плавная работа с @nuxt/ui формами

Заключение

Интеграция Valibot с формами UForm в Nuxt 3 предоставляет мощное и типобезопасное решение для валидации данных. Такой подход сочетает в себе удобство использования готовых UI-компонентов из @nuxt/ui с гибкостью и надежностью библиотеки Valibot.

Попробуйте этот подход в своем следующем проекте на Nuxt 3, и вы оцените его преимущества!


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Сколько будет 7 + 3?