Валидация форм во Vue.js
Привет, Хабр!
Валидация форм — одна из самых важных задач на сайте. Нам приходится валидировать данные на присутствие, на совпадение по паттерну, создавать асинхронные валидации, применять валидации только после снятия фокуса с поля или перед отправкой формы… Порой это становится настоящей головной болью для разработчика.
Vue.js содержит много интересных и необычных подходов к валидации, которые помогут решить ваши проблемы. Обзор под катом!
TL; DR
Используйте Vuelidate.
Частые ошибки
Валидации с помощью средств HTML5
HTML5 дал разработчикам возможность валидации форм с помощью новых атрибутов для полей и Validation API. Мы можем использовать их прямо в наших vue-шаблонах.
Вот, например, простая форма регистрации, состоящая из трех полей: поля для электронной почты, для пароля и повтора пароля. Для первых двух мы используем валидации с помощью атрибутов, для третьего — с помощью атрибутов и Validation API:
Песочница с примером
Даже в таком простом примере можно увидеть много проблем:
- Браузеры показывают только одну ошибку за один раз. Пользователю придется пытаться отправить форму несколько раз, чтобы увидеть все свои ошибки.
- Ошибки отображаются пользователю только после попытки отправки формы. Для изменения этого поведения придется написать еще тонну кода: вызывать у каждого элемента по событию blur функцию reportValidity ().
- Для стилизации полей ввода существуют только псевдоклассы : valid и : invalid, нет возможности поймать состояние, когда данные в поле ввода неверны, но пользователь еще не взаимодействовал с ним.
- Каждый браузер отображает ошибки валидации по-своему, они могут выглядеть некрасиво в вашем дизайне.
- Validation API во Vue.js неудобно использовать: приходится сохранять элементы в $refs.
Если у вас в проекте всего одна форма, и та используется только вами, то HTML5 валидации — отличный выбор. Во всех остальных остальных случаях старайтесь использовать другие подходы.
Валидации без использования библиотек
Другая частая проблема, которую я встречаю в проектах — валидации без использования библиотек.
Песочница с примером
В таком подходе нет проблем. За исключением того, что в формах с количеством полей больше одного рождается много повторяющегося кода, и каждый разработчик пишет валидации по-своему.
Лучший выход из всех проблем — пользоваться библиотеками, которые предлагает нам сообщество. На текущий момент есть два популярных решения для валидации форм:
Каждая имеет свой уникальный подход, которые мы подробно рассмотрим ниже.
vee-validate
vee-validate — библиотека для валидаций, появившаяся во времена Vue.js первой версии, имеет большое сообщество и используется в большом количестве проектов.
Возраст сказывается на весе — 31 КБайт (minified+GZIP), в полтора раза больше самого Vue.js! Связано это с тем, что библиотека содержит в себе сразу кучу вещей:
- 35 встроенных валидаторов
- Перевод ошибок на английский язык
- Директивы для валидаций
- Компоненты для валидаций
Библиотека поддерживает 41 язык для ошибок. Чтобы установить и использовать ее с нужной локализацией, требуется выполнить всего пару шагов:
npm i vee-validate
/* main.js */
import Vue from 'vue';
import VeeValidate, { Validator } from 'vee-validate';
import ru from 'vee-validate/dist/locale/ru';
Validator.localize('ru', ru);
Vue.use(VeeValidate, {
locale: 'ru',
});
/* ... */
У vee-validate есть два подхода к валидациям: с помощью директивы и с помощью компонентов.
Валидация с помощью директивы v-validate
Подход с помощью директивы очень прост: вы вешаете на поле ввода директиву v-validate, которой передаете список валидаторов. Состояние валидации и строчки ошибок затем можно получить из полей fields и errors внутри компонента.
Чтобы посмотреть ее использование на примере, давайте сделаем простую форму, которая:
— Содержит поле «Серия и номер паспорта»
— Содержит поле «Дата выдачи паспорта»
— Содержит поле «Имя»
— Добавляет атрибут disabled на кнопку отправки формы если данные неверны
Песочница с примером
Как можно было заметить, при использовании флагов внутри fields.passport_date пришлось проверить поле passport_date на присутствие — во время первого рендера у vee-validate нет информации о ваших полях и, соответственно, нет объекта с флагами. Чтобы избавиться от этой проверки, используйте специальный хелпер mapFields.
Валидации с помощью компонентов
Новый способ валидации, который появился в конце прошлого года — использование компонентов. Сами авторы рекомендуют использовать этот подход, и он отлично сочетается с новым синтаксисом слотов из Vue.js@2.6.
Библиотека предоставляет два компонента:
- ValidationProvider — компонент, в котором вы описываете валидации и в который оборачиваете поле ввода.
- ValidationObserver — компонент, который объединяет флаги валидаций нескольких ValidationProvider’ов.
Вот форма из прошлого примера, но написанная с помощью компонентов:
Песочница с примером
Остальные возможности библиотеки
Проблемы
Первая и самая большая проблема — это, конечно же, ее размер. Библиотека не поддерживает tree-shaking и выборочное добавление валидаторов. Хотите вы или нет, в вашем банде всегда будет присутствовать 2 компонента и директива валидаций, перевод на английский язык и 35 валидаторов.
Вторая проблема — из-за подхода, основанного на подписке на события, могут возникать проблемы при интеграции с другими библиотеками, которые тоже изменяют поведение полей ввода (маскеры и т.п.).
Третья проблема — более субъективная — переводы ошибок общие и некрасивые, не отражают реальной сути.
Возьмем форму из прошлых примеров. Если вы введете неправильный номер и дату паспорта, то получите такие ошибки:
Поле серия и номер паспорта имеет ошибочный формат.
Поле дата выдачи паспорта должно быть в формате dd.MM.yyyy.
Хочется заменить их на что-то более удобочитаемое:
Поле серия и номер паспорта должно быть в формате 1234 567890
Поле дата выдачи паспорта должно быть в формате ДД.ММ.ГГГГ
Vuelidate
Библиотека Vuelidate появилась в ответ на проблемы с подходами, которые содержит в себе библиотека vee-validate. Vuelidate не имеет ни обработчиков событий для полей, ни переводов для ошибок валидации.
Она требует от вас только одного — описать валидации в объекте validations. Затем она сама создаст computed-поле $v с флагами валидации полей и функциями для изменения этих флагов.
Благодаря простому подходу к валидациям, Vuelidate весит всего 3.4 КБайта (minified+GZIP), почти в 10 раз меньше vee-validate.
Устанавливается она так же просто:
npm i vuelidate
/* main.js */
import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
/* ... */
Перепишем форму из прошлого примера с использованием Vuelidate:
Песочница с примером
Кастомные валидаторы можно быстро и легко описывать с помощью функций. Если вы хотите, чтобы параметры вашего валидатора попали в объект $params, используйте специальный хелпер withParams.
Как можно заметить, поля с несколькими ошибками занимают очень много места и выглядят монструозно — решается это созданием отдельного компонента для отображения валидаций.
Остальные возможности библиотеки
Проблемы
Из проблем можно выделить разве что сравнительно скудное количество валидаторов из коробки, зачастую приходится писать свои функции для валидации.
Заключение
Библиотеку Vuelidate я использовал во многих проектах и ни разу не сталкивался с нерешаемыми проблемами. Для меня она остается лучшим выбором. Если вы заботитесь о размере своего кода и предпочитаете модельный подход к описанию валидаций — берите ее, простая документация и богатое апи позволит валидировать формы любой сложности.
Если вы делаете админку для внутреннего использования, не хотите тратить ни капли времени на строчки ошибок — выбирайте vee-validate. Она поможет быстро и без проблем написать много валидаций.
Спасибо за внимание!