Частичная валидация в Vest опирается на идею избирательного выполнения правил проверки вместо запуска всей валидационной схемы целиком. В реальных формах это критично: пользователь изменяет одно поле, и нет смысла заново прогонять десятки или сотни правил, затрагивающих остальные поля. Архитектура библиотеки позволяет разделять проверки по логическим группам и запускать их точечно.
Валидационные наборы в Vest строятся как набор тестов, объединённых в единый контекст. Каждый тест привязан к конкретному полю или логической группе полей. При обычном запуске выполняется полный прогон всей схемы, однако механизм выполнения позволяет ограничивать область проверки.
Основная цель частичной валидации:
Подход особенно важен в формах с асинхронными проверками (например, проверка уникальности логина), где каждая операция может быть затратной.
В Vest логика обычно организуется через набор тестов, сгруппированных по ключам полей. Каждое поле представляет собой независимый контекст, внутри которого выполняются правила.
import { create, test, enforce } from 'vest';
const suite = create((data = {}) => {
test('username', 'Имя пользователя обязательно', () => {
enforce(data.username).isNotEmpty();
});
test('email', 'Некорректный email', () => {
enforce(data.email).matches(/.+@.+\..+/);
});
test('password', 'Пароль слишком короткий', () => {
enforce(data.password).longerThan(6);
});
});
При таком разбиении каждое поле становится независимой единицей выполнения. Это открывает возможность запускать проверки выборочно, ориентируясь на изменённые данные.
Частичная валидация реализуется через ограничение области выполнения при запуске набора. Вместо полного прохода всей схемы применяется фильтрация тестов по ключу или группе ключей.
Типичный сценарий — обновление одного поля формы:
suite({ username: 'john' }, 'username');
В этом случае выполняются только тесты, связанные с
username, остальные блоки игнорируются.
Подобный подход снижает вычислительную нагрузку в формах с большим количеством зависимых правил.
Для более сложных форм используется группировка логики. Поля объединяются в логические сегменты, которые могут валидироваться независимо.
Пример структуры:
const suite = create((data = {}) => {
test('account.username', () => {
enforce(data.account.username).isNotEmpty();
});
test('account.email', () => {
enforce(data.account.email).matches(/.+@.+\..+/);
});
test('profile.firstName', () => {
enforce(data.profile.firstName).isNotEmpty();
});
test('profile.lastName', () => {
enforce(data.profile.lastName).isNotEmpty();
});
});
Запуск проверки может ограничиваться целой веткой:
suite(data, 'account');
или более узко:
suite(data, 'profile.firstName');
Иерархическая адресация позволяет работать с формой как с деревом состояний, где каждый узел может быть проверен отдельно.
Частичная валидация наиболее эффективно проявляется в сценарии реактивных интерфейсов. При изменении одного поля нет необходимости запускать полную проверку всей формы.
Модель поведения:
function onFieldChange(field, value) {
setFormState(prev => ({
...prev,
[field]: value
}));
const result = suite({ [field]: value }, field);
setErrors(prev => ({
...prev,
[field]: result.getErrors(field)
}));
}
Такой подход снижает количество повторных вычислений и позволяет масштабировать формы без деградации производительности.
Частичная валидация усложняется в случаях, когда одно поле зависит от другого. Например, подтверждение пароля или условные правила.
test('passwordConfirmation', () => {
enforce(data.passwordConfirmation).equals(data.password);
});
При изменении password требуется также повторная
проверка passwordConfirmation. В таких сценариях
применяется расширение области выполнения:
suite(data, ['password', 'passwordConfirmation']);
или группировка зависимых полей в один контекст.
Асинхронные правила особенно чувствительны к частичной валидации. Запросы к серверу (например, проверка уникальности email) должны выполняться только при изменении соответствующего поля.
test('email', async () => {
await enforce(data.email).isNotEmpty();
const exists = await checkEmailExists(data.email);
enforce(exists).isFalsy();
});
При частичном запуске такие проверки полностью изолируются:
suite(data, 'email');
Это предотвращает избыточные сетевые запросы при изменении других частей формы.
Частичная валидация часто комбинируется с кэшированием предыдущих результатов. Если значение поля не изменилось, повторная проверка может быть пропущена.
Логика строится вокруг сравнения предыдущего состояния и текущего значения:
if (prevState.email === nextState.email) {
return prevResult.email;
}
Такой подход особенно полезен при частых перерендерах интерфейса.
Несмотря на эффективность, частичная проверка имеет ограничения:
Баланс между полным и частичным выполнением определяется структурой формы и количеством межполевых связей.
Ключевым требованием остаётся идентичность результатов при полном и частичном выполнении. Частичная валидация не должна изменять итоговую логику проверки.
Это достигается за счёт того, что:
Таким образом, частичный запуск выступает как оптимизационный слой, не влияющий на семантику валидации.