Валидация форм в приложениях на базе Quasar может реализовываться как
встроенными средствами (rules в компонентах
QInput, QSelect и т.д.), так и через
специализированные библиотеки. При усложнении логики (асинхронные
проверки, сложные зависимости, повторное использование схем)
предпочтение отдается внешним решениям — таким как
Vuelidate и VeeValidate.
Обе библиотеки интегрируются с экосистемой Vue (включая Composition API), но имеют разные подходы:
Quasar не накладывает ограничений на использование этих библиотек, но требует корректной синхронизации с UI-компонентами.
npm install @vuelidate/core @vuelidate/validators
Пример подключения в компоненте:
import { useVuelidate } from '@vuelidate/core'
import { required, minLength, email } from '@vuelidate/validators'
import { reactive, computed } from 'vue'
export default {
setup () {
const form = reactive({
name: '',
email: ''
})
const rules = computed(() => ({
name: { required, minLength: minLength(3) },
email: { required, email }
}))
const v$ = useVuelidate(rules, form)
return { form, v$ }
}
}
Quasar использует свойства error и
error-message для отображения ошибок. Их необходимо
синхронизировать с состоянием Vuelidate.
<q-input
v-model="form.name"
label="Имя"
:error="v$.name.$error"
:error-message="v$.name.$errors[0]?.$message"
@blur="v$.name.$touch()"
/>
Ключевые моменты:
$error — флаг наличия ошибки$errors — массив ошибок с сообщениями$touch() — активирует валидацию при взаимодействииПо умолчанию валидаторы не содержат сообщений. Используется обёртка
helpers.withMessage:
import { helpers, required } from '@vuelidate/validators'
const rules = {
name: {
required: helpers.withMessage('Поле обязательно', required)
}
}
const isUnique = helpers.withAsync(async (value) => {
const res = await api.checkEmail(value)
return res.available
})
const rules = {
email: { isUnique }
}
Важно учитывать:
$pending<q-input
:loading="v$.email.$pending"
/>
const submit = async () => {
const isValid = await v$.$validate()
if (!isValid) return
// отправка данных
}
npm install vee-validate yup
yup используется для декларативного описания схем.
import { Form, Field, ErrorMessage } from 'vee-validate'
export default {
components: {
Form,
Field,
ErrorMessage
}
}
VeeValidate не знает о Quasar напрямую, поэтому используется scoped slot:
<Form v-slot="{ errors }" @submit="onSubmit">
<Field name="email" rules="required|email" v-slot="{ field, meta }">
<q-input
v-bind="field"
label="Email"
:error="meta.touched && meta.invalid"
:error-message="errors.email"
/>
</Field>
<q-btn type="submit" label="Отправить" />
</Form>
import * as yup from 'yup'
const schema = yup.object({
name: yup.string().required('Введите имя').min(3),
email: yup.string().required().email()
})
<Form :validation-schema="schema" @submit="onSubmit">
<Field name="name" v-slot="{ field, errors }">
<q-input
v-bind="field"
label="Имя"
:error="!!errors.length"
:error-message="errors[0]"
/>
</Field>
</Form>
import { useForm } from 'vee-validate'
export default {
setup () {
const { handleSubmit, errors } = useForm({
validationSchema: schema
})
const onSub mit = handleSubmit(values => {
console.log(values)
})
return { onSubmit, errors }
}
}
import { useField } from 'vee-validate'
const { value, errorMessage, meta } = useField('email')
<q-input
v-model="value"
:error="meta.touched && meta.invalid"
:error-message="errorMessage"
/>
| Характеристика | Vuelidate | VeeValidate |
|---|---|---|
| Подход | Реактивная модель | Схема + формы |
| Простота интеграции | Высокая | Средняя |
| Асинхронная логика | Встроена | Через schema/кастом |
| Масштабируемость | Хорошая | Отличная |
| Типизация | Ограниченная | Лучшая (с Yup/Zod) |
Использование Vuelidate оправдано, если:
Использование VeeValidate оправдано, если:
Quasar предоставляет компонент QForm, который может
использоваться совместно с обеими библиотеками.
<q-form @submit.prevent="submit">
<q-input ... />
</q-form>
QForm используется только как контейнер, логика
валидации остаётся во Vuelidate.
QForm обычно не используется, так как Form
из VeeValidate уже выполняет его роль.
$touch() при blurvalidateOnBlur: true$autoDirtyvalidateOnInputПри создании собственных компонентов необходимо проксировать свойства:
props: {
modelValue: String,
error: Boolean,
errorMessage: String
}
И использовать их внутри:
<q-input
:model-value="modelValue"
:error="error"
:error-message="errorMessage"
/>
Это позволяет интегрировать компонент с обеими библиотеками.
v$.email.$errors.push({
$message: 'Email уже занят'
})
setErrors({
email: 'Email уже занят'
})
v-model и Field$touch() в Vuelidatemeta.touched в VeeValidateТакое разделение позволяет создавать масштабируемые и поддерживаемые формы без привязки к конкретной реализации UI.