Table of Contents
Perché le funzioni di convalida avanzate del modulo
Mentre gli attributi HTML5 forniscono una solida base, spesso cadono breve quando è necessario applicare regole aziendali complesse, fornire feedback in tempo reale, o creare un'esperienza utente fluida attraverso diversi browser. La validazione basata su JavaScript ti dà il pieno controllo su quando e come funziona la validazione, permettendo di implementare regole personalizzate come i misuratori di forza di password, i nomi di campo di pattern-mat
La validazione lato client riduce anche il carico del server e accelera il loop di feedback per gli utenti. Invece di inviare un modulo e in attesa di una risposta del server, gli errori vengono catturati immediatamente. Tuttavia, è fondamentale ricordare che la convalida lato client è un convenienza[, non una misura di sicurezza.
In questa guida, cammineremo attraverso la costruzione di un sistema di validazione avanzato completo utilizzando JavaScript vaniglia. Imparerai a definire regole personalizzate, visualizzare messaggi di errore dinamici, convalidare più campi insieme e mantenere il codice manutenbile.
Comprendere i limiti della convalida HTML5
Gli attributi HTML5 come , , e sono grandi per i semplici controlli, ma non hanno flessibilità.
- Nessun cross-field validation[[] – Non puoi confermare che una password e un campo di conferma corrispondono solo usando HTML5.
- Messaggi di errore preferiti[[] – Le tooltips integrate del browser sono inconsistenti tra i browser e non possono essere modellate completamente.
- Nessun aggiornamento in tempo reale[[] – La convalida HTML5 in genere spara solo su presentazione del modulo, non su ogni tasto di tasti.
- API di convalida di contrasto[[] – Mentre potente, si basa ancora sulle regole integrate del browser e non ha la capacità di definire facilmente la logica personalizzata complessa.
Con gli ascoltatori degli eventi e le funzioni personalizzate, è possibile creare una validazione sia espressiva che facile da usare.
Impostazione della struttura del modulo HTML
Ecco un esempio che include campi per nome utente, email, password e conferma password. Abbiamo aggiunto attributi per l'accessibilità e vuoto elementi che manterranno messaggi di errore.
<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>
Si noti l'attributo sul modulo. Questo indica al browser di disattivare la propria validazione integrata in modo da poter gestire tutto con JavaScript. Useremo CSS per mostrare o nascondere messaggi di errore e aggiungere feedback visuali (ad esempio, bordi rossi) a campi non validi.
Progettazione di una logica di convalida centrale
Invece di spargere il codice di validazione tra i gestori degli eventi, creiamo un oggetto centrale che contiene regole personalizzate. Ogni regola è una funzione che restituisce [ (valida) o (invalida) insieme a un messaggio di errore opzionale.
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.';
}
};
Si noti che i validatori possono essere parametrizzati – restituisce una funzione che si aspetta il valore. Il validatore [ riceve l'id di un altro campo e utilizza (un oggetto ] per confrontare i valori. Questo modello è altamente riutilizzabile.
Creazione di regole personalizzate per ogni campo
Definire quali validatori si applicano a ciascun campo. Questa mappatura è un oggetto semplice in cui le chiavi sono nomi di campo e valori sono array di funzioni di validatore.
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')
]
};
Puoi facilmente aggiungere una nuova regola personalizzata, come ad esempio un controllo che il nome utente non è già preso (valida asinc), aggiungendo una funzione asincrona all'elenco.
Validazione in esecuzione su modulo Submission
Collegare un ascoltatore di eventi al modulo che impedisce la presentazione, gestisce tutti i validatori e raccoglie errori. Se non si trovano errori, il modulo è permesso di inviare.
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);
}
});
La funzione isera su ogni campo, gestisce i suoi validatori e raccoglie messaggi di errore.
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;
}
Visualizzazione di Feedback di convalida in tempo reale
Gli utenti beneficiano di vedere gli errori come si digitano, non solo su presentazione. Aggiungi gli ascoltatori degli eventi per e [] su ogni campo. Per evitare gli utenti schiaccianti, un buon modello è quello di convalidare su blur (quando lasciano il campo) e poi ri-validate su ogni input successivo fino a quando l'errore non viene risolto.
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);
}
});
});
La funzione controlla solo le regole per un singolo campo e aggiorna l'intervallo di errore corrispondente.
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);
}
Errori di dimensionamento e Stati di successo
Usare CSS per modificare l'aspetto visivo dei campi validi/invalidi. Le funzioni e [ aggiungono o rimuovono le classi CSS e aggiornano l'attributo per l'accessibilità.
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 = '';
}
Il corrispondente CSS potrebbe essere:
.is-invalid {
border-color: #dc3545;
}
.is-valid {
border-color: #28a745;
}
.error-message {
color: #dc3545;
font-size: 0.875rem;
min-height: 1.2em;
}
Costruire un Meter di Forza password
Un contatore di forza della password fornisce un feedback visivo che incoraggia gli utenti a creare password più forti. Piuttosto che un semplice passaggio / fatica, è possibile calcolare un punteggio e mostrare una barra di progresso.
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
}
Attaccare un evento al campo password che aggiorna un elemento metro. È possibile mappare il punteggio ad un'etichetta come 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';
});
Regole doganali asincroni
Alcuni controlli di validazione richiedono una andata e ritorno al server, come ad esempio il controllo se un nome utente o un'email è già registrato. Per gestire questo senza bloccare l'interfaccia utente, è possibile rendere il convalidatore una funzione asinclinabile e regolare la logica di convalida per attendere il risultato.
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.';
}
}
};
Quindi aggiorna per supportare i validatori asincroni. È inoltre necessario gestire lo stato di caricamento per evitare più richieste simultanee (sotto la richiesta).
Migliori Pratiche per le Forme di Produzione
- Sempre convalidare lato server[[]. La convalida lato client è una convenienza, mai uno strato di sicurezza.
- Debounce async check[[]. Se si convalida su tasti per le chiamate server, utilizzare un timer di debounce (ad esempio, 300 ms) per evitare di martellare il server.
- Utilizza l'API di convalida di configurazione[[] quando possibile. Puoi mescolare JavaScript personalizzato con i metodi integrati e per un approccio ibrido. Questo è utile per i campi che hanno vincoli standard ma hanno bisogno di messaggi personalizzati.
- Aggiungi la convalida[]. Usa per associare messaggi di errore agli input. Aggiornamento [ e ] regioni in modo che i lettori dello schermo annuncino errori.
- Test tra browser e dispositivi[[[]]. La gestione di eventi touch, tastiere virtuali e dimensioni dello schermo diverse è essenziale.
- Tenere a mente le prestazioni[]. Per forme complesse con molti campi, convalida batch o utilizzando [ per gli aggiornamenti dell'interfaccia utente possono impedire il blocco.
- Provi messaggi di errore chiari e costruttivi[[[]]. Dite all'utente esattamente cosa c'è di sbagliato e come risolverlo. Evitare messaggi generici come "input non valido".
Andare oltre: Convalida modulare con le biblioteche
Se il vostro progetto richiede un alto livello di regole personalizzate e validazione in tempo reale, potreste considerare una libreria leggera come [Validate.js o l' built-in Constraint Validation API. Tuttavia, l'approccio JavaScript vaniglia dimostrato in questo articolo vi dà il pieno controllo e zero dipendenze, che è ideale per le linee guida di performance-
Puoi anche combinare la validazione personalizzata con i quadri moderni come React o Vue, ma i concetti fondamentali di separare le regole dalla presentazione rimangono gli stessi.
Pitfalls comuni da evitare
- Validare solo su presentazione[]. Gli utenti preferiscono feedback immediato.
- Non resettare gli errori quando i campi diventano validi[[]. Una volta che un utente risolve un errore, cancellare il messaggio. La logica in tempo reale in questo articolo gestisce automaticamente.
- .Essumendo l'utente obbedirà alla convalida[]. JavaScript può essere disabilitato interamente.
- Over-complicare regole[[]. Tenere i validatori semplici e concentrati. Una funzione dovrebbe testare una preoccupazione. Combinarli per applicare più criteri.
Conclusioni
Costruire la validazione di moduli JavaScript personalizzati è un'abilità essenziale per creare applicazioni web lucida e facile da usare. Strutturando il codice intorno alle funzioni di validatore riutilizzabili e feedback in tempo reale, è possibile gestire tutto, dai campi base richiesti ai metri di forza di password complessi e confronti cross-field. Gli esempi forniti in questo articolo ti danno una solida base per adattarsi ai tuoi progetti.
Ricordate che la validazione è parte fondamentale dell'esperienza dell'utente. Controllate attentamente i vostri moduli, ascoltate il feedback degli utenti e abbinate sempre la validazione del lato client con i controlli robusti sul lato server. Per ulteriori informazioni, consultate l'articolo W3C Web Accessibility Initiative guida sulla convalida della forma e l'articolo ]]MDN sulla convalida della forma]]]
Seguendo i modelli e le migliori pratiche qui delineate, creerete forme che sono sia sicure che piacevoli da usare. Iniziate sperimentando i frammenti di codice, personalizzate le regole per abbinare la vostra logica aziendale, e iterate basato sulle interazioni reali dell'utente.