Как использовать Javascript для расширенной проверки формы с помощью пользовательских правил
Почему важна расширенная проверка формы
В то время как атрибуты HTML5 обеспечивают прочную базовую линию, они часто не дотягивают, когда вам нужно обеспечить сложные бизнес-правила, обеспечить обратную связь в реальном времени или создать плавный пользовательский интерфейс в разных браузерах. Валидация на основе JavaScript дает вам полный контроль над тем, когда и как проходит валидация, позволяя вам реализовывать пользовательские правила, такие как счетчики прочности паролей, сопоставление шаблонов для имен пользователей, зависимая логика поля и асинхронные проверки, такие как уже принято имя пользователя.
Проверка на стороне клиента также снижает нагрузку на сервер и ускоряет цикл обратной связи для пользователей. Вместо того, чтобы отправлять форму и ждать ответа сервера, ошибки сразу же пойманы. Однако важно помнить, что проверка на стороне клиента является удобством , а не мерой безопасности. Злоумышленники могут обходить любую проверку JavaScript, поэтому всегда сочетайте проверку на стороне клиента с надежной проверкой на стороне сервера.
В этом руководстве мы рассмотрим создание полной расширенной системы проверки с использованием ванильного JavaScript. Вы узнаете, как определять пользовательские правила, отображать динамические сообщения об ошибках, проверять несколько полей вместе и поддерживать работоспособность вашего кода. Каждый раздел включает готовые к производству фрагменты кода, которые вы можете немедленно адаптировать.
Понимание ограничений валидации HTML5
HTML5 атрибуты, такие как , и , отлично подходят для простых проверок, но им не хватает гибкости.
- Никакой проверки поперечного поля — Вы не можете подтвердить, что пароль и подтверждение совпадают полей, используя только HTML5.
- Ограниченные сообщения об ошибках — Встроенные подсказки браузера непоследовательны для разных браузеров и не могут быть полностью оформлены.
- Никакого обновления в реальном времени — HTML5 валидация обычно запускается только при подаче формы, а не на каждом нажатии клавиши.
- API проверки ограничений — Несмотря на свою мощь, он по-прежнему полагается на встроенные правила браузера и не имеет возможности легко определять сложную пользовательскую логику.
JavaScript заполняет эти пробелы. С помощью слушателей событий и пользовательских функций вы можете создать валидацию, которая является экспрессивной и удобной для пользователя.
Настройка структуры HTML-формы
Начните с чистой семантической формы. Вот пример, который включает поля для имени пользователя, электронной почты, пароля и пароля подтверждения. Мы добавили атрибуты для доступности и пустые элементы , которые будут содержать сообщения об ошибках.
<form id="registrationForm" novalidate>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" placeholder="e.g. johndoe" required>
<span id="usernameError" class="error-message" role="alert"></span>
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" id="email" name="email" placeholder="[email protected]" required>
<span id="emailError" class="error-message" role="alert"></span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" placeholder="At least 8 characters" required>
<span id="passwordError" class="error-message" role="alert"></span>
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password</label>
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="Repeat password" required>
<span id="confirmPasswordError" class="error-message" role="alert"></span>
</div>
<button type="submit">Register</button>
</form>
Обратите внимание на атрибут в форме. Это говорит браузеру отключить собственную встроенную проверку, чтобы мы могли обрабатывать все с помощью JavaScript. Мы будем использовать CSS для отображения или скрытия сообщений об ошибках и добавления визуальной обратной связи (например, красных границ) в недействительные поля.
Разработка центральной логики валидации
Вместо того, чтобы разбрасывать код проверки по обработчикам событий, мы создаем центральный объект, который содержит пользовательские правила. Каждое правило - это функция, которая возвращает (действительно) или (недействительно) вместе с дополнительным сообщением об ошибке. Этот подход делает код простым в расширении и обслуживании.
const validators = {
required: (value) => value.trim() !== '' || 'This field is required.',
email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || 'Please enter a valid email address.',
minLength: (min) => (value) => value.length >= min || `Must be at least ${min} characters.`,
passwordStrength: (value) => {
const errors = [];
if (value.length < 8) errors.push('At least 8 characters.');
if (!/[A-Z]/.test(value)) errors.push('One uppercase letter.');
if (!/[0-9]/.test(value)) errors.push('One number.');
if (!/[!@#$%^&*]/.test(value)) errors.push('One special character.');
return errors.length === 0 || errors.join(' ');
},
match: (otherFieldId) => (value, formData) => {
const otherValue = formData.get(otherFieldId);
return value === otherValue || 'Passwords do not match.';
}
};
Обратите внимание, что валидаторы могут быть параметризированы - возвращает функцию, которая ожидает значения. валидатор получает идентификатор другого поля и использует (объект ) для сравнения значений. Этот шаблон очень многоразовый.
Создание пользовательских правил для каждой области
Определение того, какие валидаторы применяются к каждому полю. Это отображение является простым объектом, где ключи являются именами полей, а значения — массивами функций валидатора.
const fieldRules = {
username: [
validators.required,
validators.minLength(3),
(value) => /^[a-zA-Z0-9_]+$/.test(value) || 'Usernames can only contain letters, numbers, and underscores.'
],
email: [
validators.required,
validators.email
],
password: [
validators.required,
validators.passwordStrength
],
confirmPassword: [
validators.required,
validators.match('password')
]
};
Вы можете легко добавить новое пользовательское правило, например, проверить, что имя пользователя еще не взято (проверка асинхронизации), добавив функцию асинхронизации в список.
Проверка по форме подачи
Прикрепить слушателя мероприятия к форме, которая препятствует подаче, запускает все валидаторы и собирает ошибки.Если ошибок не обнаружено, форма допускается к подаче.
const form = document.getElementById('registrationForm');
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(form);
const errors = validateForm(formData);
if (Object.keys(errors).length === 0) {
// All valid – you can submit programmatically or send via fetch
console.log('Form is valid. Submitting...');
// form.submit();
} else {
displayErrors(errors);
}
});
Функция итерируется по каждому полю, запускает свои валидаторы и собирает сообщения об ошибках.
function validateForm(formData) {
const errors = {};
for (const [fieldName, rules] of Object.entries(fieldRules)) {
const value = formData.get(fieldName) || '';
for (const rule of rules) {
const result = rule(value, formData);
if (result !== true) {
errors[fieldName] = result; // result is the error string
break; // stop after first failure for this field
}
}
}
return errors;
}
Отзывы о валидации в реальном времени
Пользователи получают выгоду от просмотра ошибок при их вводе, а не только при отправке. Добавьте слушателей событий для и в каждом поле. Чтобы избежать подавляющих пользователей, хорошая схема заключается в проверке размытия (когда они покидают поле), а затем повторном подтверждении на каждом последующем входе до тех пор, пока ошибка не будет решена.
document.querySelectorAll('#registrationForm input').forEach((input) => {
input.addEventListener('blur', () => {
validateField(input.id, input.value);
});
input.addEventListener('input', () => {
// If the field currently has an error, re-validate on each keystroke
const errorSpan = document.getElementById(input.id + 'Error');
if (errorSpan.textContent !== '') {
validateField(input.id, input.value);
}
});
});
Функция проверяет только правила для одного поля и обновляет соответствующий интервал ошибок.
function validateField(fieldId, value) {
const formData = new FormData(form);
formData.set(fieldId, value);
const rules = fieldRules[fieldId];
if (!rules) return;
for (const rule of rules) {
const result = rule(value, formData);
if (result !== true) {
setFieldError(fieldId, result);
return;
}
}
clearFieldError(fieldId);
}
Ошибки стиля и состояния успеха
Используйте CSS для изменения визуального вида действительных/недействительных полей. Функции и добавляют или удаляют классы CSS и обновляют атрибут для доступности.
function setFieldError(fieldId, message) {
const input = document.getElementById(fieldId);
const errorSpan = document.getElementById(fieldId + 'Error');
input.classList.add('is-invalid');
input.classList.remove('is-valid');
input.setAttribute('aria-invalid', 'true');
errorSpan.textContent = message;
}
function clearFieldError(fieldId) {
const input = document.getElementById(fieldId);
const errorSpan = document.getElementById(fieldId + 'Error');
input.classList.remove('is-invalid');
input.classList.add('is-valid');
input.setAttribute('aria-invalid', 'false');
errorSpan.textContent = '';
}
Соответствующим CSS может быть:
.is-invalid {
border-color: #dc3545;
}
.is-valid {
border-color: #28a745;
}
.error-message {
color: #dc3545;
font-size: 0.875rem;
min-height: 1.2em;
}
Создание пароля Strength Meter
Измеритель прочности пароля обеспечивает визуальную обратную связь, которая побуждает пользователей создавать более сильные пароли.Вместо простого прохода / отказа вы можете вычислить балл и показать планку прогресса.
function passwordStrengthScore(password) {
let score = 0;
if (password.length >= 8) score += 1;
if (password.length >= 12) score += 1;
if (/[A-Z]/.test(password)) score += 1;
if (/[a-z]/.test(password)) score += 1;
if (/[0-9]/.test(password)) score += 1;
if (/[^A-Za-z0-9]/.test(password)) score += 1;
return score; // 0-6
}
Прикрепите событие к полю пароля, которое обновляет элемент метра. Вы можете сопоставить оценку с такой меткой, как Weak (0-2), Fair (3-4), Strong (5-6).
const passwordMeter = document.getElementById('passwordStrengthMeter');
const passwordInput = document.getElementById('password');
passwordInput.addEventListener('input', () => {
const score = passwordStrengthScore(passwordInput.value);
const percentage = (score / 6) * 100;
passwordMeter.value = percentage;
passwordMeter.style.accentColor = score < 3 ? '#dc3545' : score < 5 ? '#ffc107' : '#28a745';
});
Асинхронные пользовательские правила
Некоторые проверки валидации требуют круглого пути к серверу, например, проверка, зарегистрировано ли имя пользователя или электронная почта. Чтобы справиться с этим, не блокируя пользовательский интерфейс, вы можете сделать свой валидатор функцией асинхронизации и настроить логику проверки, чтобы дождаться результата.
const asyncValidators = {
uniqueUsername: async (value) => {
try {
const response = await fetch(`/api/check-username?username=${encodeURIComponent(value)}`);
const data = await response.json();
return data.available || 'Username is already taken.';
} catch {
return 'Could not verify username availability.';
}
}
};
Затем обновите для поддержки валидаторов асинхронизации. Вы также должны обрабатывать состояние загрузки, чтобы избежать нескольких одновременных запросов (объявить запрос).
Лучшие практики для производственных форм
- Всегда проверяйте серверную сторону . Проверка на стороне клиента — это удобство, никогда не уровень безопасности. Используйте те же правила на бэкэнде, чтобы отклонить вредоносные или искаженные данные.
- Проверка асинхронизации дебюнзаций Если вы проверяете нажатие клавиши для вызовов сервера, используйте таймер дебюнкции (например, 300 мс), чтобы избежать удара по серверу.
- По возможности используйте API проверки ограничений . Вы можете смешать пользовательский JavaScript со встроенными и методами для гибридного подхода. Это полезно для полей, которые имеют стандартные ограничения, но нуждаются в пользовательских сообщениях.
- Сделайте проверку доступной. Используйте , чтобы связать сообщения об ошибках с входами. Обновите и области, чтобы читатели экрана сообщали об ошибках.
- Тестирование в браузерах и устройствах. Обработка сенсорных событий, виртуальных клавиатур и различных размеров экрана имеет важное значение. Также тестируйте с автозаполнением браузера, которое может запускать события в неожиданных заказах.
- Поддерживайте производительность в уме Для сложных форм со многими полями пакетная валидация или использование для обновлений пользовательского интерфейса может предотвратить jank.
- Предоставьте четкие, конструктивные сообщения об ошибках. Расскажите пользователю, что именно не так и как это исправить. Избегайте общих сообщений, таких как «Недействительный ввод». Вместо этого скажите «Пароль должен включать по крайней мере одно число».
Далее: Модульная валидация библиотек
Если ваш проект требует высокого уровня пользовательских правил и проверки в реальном времени, вы можете рассмотреть легкую библиотеку, такую как Validate.js или встроенный API проверки ограничений . Однако подход ванильного JavaScript, продемонстрированный в этой статье, дает вам полный контроль и нулевые зависимости, что идеально подходит для приложений, чувствительных к производительности, или когда вам нужно следовать конкретным рекомендациям по дизайну.
Вы также можете комбинировать кастомную валидацию с современными фреймворками, такими как React или Vue, но основные концепции отделения правил от представления остаются прежними.
Обычные подводные камни, чтобы избежать
- Проверка только по представлению. Пользователи предпочитают немедленную обратную связь. Как минимум, проверка на размытие для каждого поля.
- Не сбрасывать ошибки, когда поля становятся действительными. Как только пользователь исправляет ошибку, очистите сообщение. Логика реального времени в этой статье обрабатывает это автоматически.
- Предполагая, что пользователь будет подчиняться валидации. JavaScript может быть полностью отключен. Всегда резервное копирование каждой проверки с логикой на стороне сервера.
- Сверхсложные правила. Держите валидаторы простыми и сфокусированными. Функция должна проверять одну проблему. Объедините их для обеспечения соблюдения нескольких критериев.
Заключение
Создание пользовательской проверки формы JavaScript является важным навыком для создания полированных, удобных для пользователя веб-приложений. Структурируя свой код вокруг функций многоразового валидатора и обратной связи в режиме реального времени, вы можете обрабатывать все, от базовых требуемых полей до сложных счетчиков прочности паролей и сравнений поперечного поля. Примеры, приведенные в этой статье, дают вам прочную основу для адаптации к вашим собственным проектам.
Помните, что валидация является важной частью пользовательского опыта. Тщательно проверяйте свои формы, слушайте отзывы пользователей и всегда сочетайте проверку на стороне клиента с надежными проверками на стороне сервера. Для дальнейшего чтения обратитесь к руководству по валидации формы W3C Web Accessibility Initiative и статье MDN по валидации формы .
Следуя шаблонам и лучшим практикам, изложенным здесь, вы создадите формы, которые являются безопасными и приятными в использовании.Начните с экспериментов с фрагментами кода, настройте правила в соответствии с вашей бизнес-логикой и итерируйте на основе реальных взаимодействий с пользователем.