Hallo Habr!
Die Formularvalidierung ist eine der wichtigsten Aufgaben auf der Website. Wir müssen die Daten auf Anwesenheit überprüfen, um mit dem Muster übereinzustimmen, asynchrone Überprüfungen zu erstellen, Überprüfungen erst anzuwenden, nachdem der Fokus aus dem Feld entfernt wurde oder bevor das Formular gesendet wird ... Manchmal wird dies für den Entwickler zu einem echten Problem.
Vue.js enthält viele interessante und ungewöhnliche Validierungsansätze, mit denen Sie Ihre Probleme lösen können. Übersicht unter dem Schnitt!
TL; DR
Verwenden Sie
Vuelidate .
Häufige Fehler
HTML5-Validierungen
Mit HTML5 konnten Entwickler Formulare mithilfe
neuer Feldattribute und der Validierungs-API validieren. Wir können sie direkt in unseren Vue-Vorlagen verwenden.
Hier ist zum Beispiel ein einfaches Registrierungsformular, das aus drei Feldern besteht: Felder für E-Mail, für Passwort und Passwortwiedergabe. Für die ersten beiden verwenden wir Validierungen mit Attributen, für die dritte mit Attributen und der Validierungs-API:
<template> <form @submit.prevent="someAction()"> <input v-model="email" type="email" required> <input v-model="password" type="password" required> <input v-model="repeatedPassword" type="password" required ref="repeatedPasswordEl"> <button type="submit"> </button> </form> </template> <script> export default { data() { return { email: null, password: null, repeatedPassword: null, }; }, watch: { repeatedPassword: 'checkPasswordsEquality', password: 'checkPasswordsEquality', }, methods: { checkPasswordsEquality() { const { password, repeatedPassword } = this; const { repeatedPasswordEl } = this.$refs; if (password !== repeatedPassword) { repeatedPasswordEl.setCustomValidity( ' ', ); } else { repeatedPasswordEl.setCustomValidity(''); } }, }, }; </script>
Sandbox mit einem BeispielSelbst in einem so einfachen Beispiel können Sie viele Probleme sehen:
- Browser zeigen jeweils nur einen Fehler an. Der Benutzer muss mehrmals versuchen, das Formular zu senden, um alle Fehler anzuzeigen.
- Fehler werden dem Benutzer erst angezeigt, nachdem er versucht hat, das Formular zu senden. Um dieses Verhalten zu ändern, müssen Sie eine weitere Tonne Code schreiben: Rufen Sie die Funktion reportValidity () für jedes Element des Unschärfeereignisses auf.
- Für die Gestaltung von Eingabefeldern gibt es nur Pseudoklassen: gültig und: ungültig. Es gibt keine Möglichkeit, einen Status abzufangen, wenn die Daten im Eingabefeld falsch sind, der Benutzer jedoch noch nicht mit ihnen interagiert hat.
- Jeder Browser zeigt Validierungsfehler auf seine eigene Weise an. Sie sehen in Ihrem Design möglicherweise hässlich aus.
- Die Validierungs-API in Vue.js ist unpraktisch: Sie müssen Elemente in $ refs speichern.
Wenn Sie nur ein Formular im Projekt haben und es nur von Ihnen verwendet wird, ist die HTML5-Validierung eine ausgezeichnete Wahl. Versuchen Sie in allen anderen Fällen, andere Ansätze zu verwenden.
Bibliotheksvalidierungen
Ein weiteres häufiges Problem, auf das ich in Projekten stoße, ist die Bibliotheksvalidierung.
<template> <form @submit.prevent="someAction()"> <input v-model="email" type="email" @blur="isEmailTouched = true" :class="{ error: isEmailError }" > <div v-if="isEmailError"> </div> <button :disabled="!isEmailValid" type="submit"> </button> </form> </template> <script> const emailCheckRegex = /^... RegExp Email...$/; export default { data() { return { email: null, isEmailTouched: false, }; }, computed: { isEmailValid() { return emailCheckRegex.test(this.email); }, isEmailError() { return !this.isEmailValid && this.isEmailTouched; }, }, }; </script>
Sandbox mit einem BeispielBei diesem Ansatz gibt es kein Problem. Abgesehen davon, dass in Formularen mit mehr als einem Feld viel wiederholter Code geboren wird und jeder Entwickler Validierungen auf seine eigene Weise schreibt.
Der beste Ausweg aus allen Problemen ist die Nutzung der Bibliotheken, die uns die Community anbietet. Derzeit gibt es zwei beliebte Formularvalidierungslösungen:
Jedes hat seinen eigenen Ansatz, auf den wir weiter unten näher eingehen werden.
vee-validieren
vee-validate - Eine Bibliothek für Validierungen, die in der ersten Version von Vue.js veröffentlicht wurde, eine große Community hat und in einer großen Anzahl von Projekten verwendet wird.
Alter beeinflusst Gewicht - 31 KB (minimiert + GZIP), eineinhalb Mal mehr als Vue.js selbst! Dies liegt an der Tatsache, dass die Bibliothek sofort eine Reihe von Dingen enthält:
- 35 eingebaute Validatoren
- Englische Übersetzung von Fehlern
- Validierungsrichtlinien
- Validierungskomponenten
Die Bibliothek unterstützt 41 Sprachen für Fehler. Um es mit der gewünschten Lokalisierung zu installieren und zu verwenden, müssen Sie nur einige Schritte ausführen:
npm i vee-validate
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 hat zwei Ansätze zur Validierung: Verwendung der Direktive und Verwendung von Komponenten.
Validierung mit der v-validate-Direktive
Der Ansatz mit der Direktive ist sehr einfach: Sie setzen die v-validate-Direktive in das Eingabefeld, an das Sie die Liste der Validatoren übergeben. Validierungsstatus und Fehlerzeilen können dann aus den Feldern Felder und Fehler innerhalb der Komponente abgerufen werden.
Um die Verwendung als Beispiel zu sehen, erstellen wir ein einfaches Formular, das:
- Enthält das Feld "Serien- und Passnummer"
- Enthält das Feld "Ausstellungsdatum des Passes"
- Enthält das Feld "Name"
- Fügt das Attribut deaktiviert zur Schaltfläche "Senden" des Formulars hinzu, wenn die Daten falsch sind
<template> <form @submit.prevent="someAction()"> <div> <input type="text" v-model="passportData" v-validate="{ required: true, regex: /^\d{4} \d{6}$/ }" data-vv-as=" " name="passport_data" > <span v-if="errors.has('passport_data')"> {{ errors.first('passport_data') }} </span> </div> <div> <input type="text" v-model.lazy="passportDate" v-validate="{ required: true, date_format: 'dd.MM.yyyy' }" data-vv-as=" " name="passport_date" > <span v-if="fields.passport_date && fields.passport_date.touched && fields.passport_date.invalid" > {{ errors.first('passport_date') }} </span> </div> <div> <input type="text" v-model="name" v-validate.continues="{ required: true, alpha: true, max: 10 }" data-vv-as="" name="name" > <span v-for="error in errors.collect('name')" :key="error" > {{ error }} </span> </div> <button type="submit" :disabled="!isFormValid" > </button> </form> </template> <script> export default { data() { return { passportData: null, name: null, passportDate: null, }; }, computed: { </script>
Sandbox mit einem BeispielWie Sie sehen können, musste ich bei Verwendung der Flags in fields.passport_date das Feld passport_date auf Vorhandensein überprüfen. Beim ersten Rendern enthält vee-validate keine Informationen zu Ihren Feldern und dementsprechend gibt es kein Objekt mit Flags. Verwenden Sie den speziellen
mapFields- Helfer, um diese Prüfung zu
entfernen .
Komponentenvalidierungen
Die neue Validierungsmethode, die Ende letzten Jahres eingeführt wurde, ist die Verwendung von Komponenten. Die Autoren selbst empfehlen diesen Ansatz und er passt gut zur neuen Slot-Syntax von Vue.js@2.6.
Die Bibliothek bietet zwei Komponenten:
- ValidationProvider - eine Komponente, in der Sie Validierungen beschreiben und in die Sie das Eingabefeld einschließen.
- ValidationObserver - eine Komponente, die die Validierungsflags mehrerer ValidationProvider kombiniert.
Hier ist ein Formular aus einem früheren Beispiel, das jedoch mit Komponenten geschrieben wurde:
<template> <ValidationObserver v-slot="{ valid }"> <form @submit.prevent="doAction()"> <ValidationProvider name=" " :rules="{ required: true, regex: /^\d{4} \d{6}$/ }" v-slot="{ errors }" > <input type="text" v-model="passportData"> <span v-if="errors[0]"> {{ errors[0] }} </span> </ValidationProvider> <ValidationProvider name=" " :rules="{ required: true, date_format: 'dd.MM.yyyy' }" v-slot="{ errors }" mode="lazy" > <input type="text" v-model="passportDate"> <span v-if="errors[0]"> {{ errors[0] }} </span> </ValidationProvider> <ValidationProvider name="" :rules="{ required: true, alpha: true, max: 10 }" v-slot="{ errors }" :bails="false" > <input type="text" v-model="name"> <span v-for="error in errors" :key="error" > {{ error }} </span> </ValidationProvider> <button type="submit" :disabled="!valid"> </button> </form> </ValidationObserver> </template> <script> import { ValidationProvider, ValidationObserver } from 'vee-validate'; export default { components: { ValidationProvider, ValidationObserver, }, data() { return { passportData: null, passportDate: null, name: null, }; }, }; </script>
Sandbox mit einem BeispielAndere Bibliotheksfunktionen
Die Probleme
Das erste und größte Problem ist natürlich seine Größe. Die Bibliothek unterstützt kein Baumschütteln und selektives Hinzufügen von Validatoren. Ob Sie es mögen oder nicht, Ihre Bande wird immer 2 Komponenten und eine Validierungsrichtlinie, eine Übersetzung ins Englische und 35 Validatoren haben.
Das zweite Problem ist auf den ereignisbasierten Abonnementansatz zurückzuführen. Bei der Integration in andere Bibliotheken, die ebenfalls das Verhalten von Eingabefeldern (Maskierer usw.) ändern, können Probleme auftreten.
Das dritte Problem - ein subjektiveres - die Übersetzungen von Fehlern sind allgemein und hässlich, spiegeln nicht das wahre Wesen wider.
Nehmen Sie das Formular aus früheren Beispielen. Wenn Sie die falsche Nummer und das falsche Datum des Reisepasses eingeben, werden folgende Fehler angezeigt:
. dd.MM.yyyy.
Ich möchte sie durch etwas Lesbareres ersetzen:
1234 567890 ..
Vuelidate
Die Vuelidate-Bibliothek wurde als Reaktion auf Probleme mit den in der V-Validate-Bibliothek enthaltenen Ansätzen angezeigt. Vuelidate verfügt weder über Ereignishandler für Felder noch über Übersetzungen für Validierungsfehler.
Sie müssen nur eines tun - um Validierungen im Validierungsobjekt zu beschreiben. Dann erstellt sie selbst ein berechnetes Feld $ v mit Feldvalidierungsflags und Funktionen zum Ändern dieser Flags.
Dank seines einfachen Validierungsansatzes wiegt Vuelidate nur 3,4 KB (minimiert + GZIP), fast zehnmal weniger als die V-Validierung.
Es ist genauso einfach zu installieren:
npm i vuelidate
import Vue from 'vue' import Vuelidate from 'vuelidate' Vue.use(Vuelidate)
Schreiben Sie das Formular aus dem vorherigen Beispiel mit Vuelidate neu:
<template> <form @submit.prevent="someAction()"> <div> <input type="text" v-model="passportData"> <span v-if="$v.passportData.$invalid"> 1234 567890 </span> </div> <div> <input type="text" v-model="passportDate" @blur="$v.passportDate.$touch()"> <span v-if="$v.passportDate.$error"> .. </span> </div> <div> <input type="text" v-model.lazy="$v.passportDate.$model"> <span v-if="$v.passportDate.$error"> .. </span> </div> <div> <input type="text" v-model="name" @blur="$v.name.$touch()"> <span v-if="$v.name.$error"> <template v-if="!$v.name.maxLength"> {{ $v.name.$params.maxLength.max }} </template> <template v-else-if="!$v.name.alpha"> </template> <template v-else> </template> </span> </div> <button type="submit" :disabled="$v.$invalid"> </button> </form> </template> <script> import { required, maxLength } from 'vuelidate/lib/validators'; import moment from 'moment'; export default { data() { return { passportData: null, name: null, passportDate: null, }; }, </script>
Sandbox mit einem BeispielBenutzerdefinierte Validatoren können mithilfe von Funktionen schnell und einfach beschrieben werden. Wenn Sie möchten, dass Ihre Validator-Parameter in das $ params-Objekt fallen, verwenden Sie den speziellen
withParams- Helfer.
Wie Sie sehen können, nehmen Felder mit mehreren Fehlern viel Platz ein und sehen monströs aus. Dies wird gelöst, indem eine separate Komponente für die Anzeige von Validierungen erstellt wird.
Andere Bibliotheksfunktionen
Die Probleme
Von den Problemen kann man die vergleichsweise geringe Anzahl von Validatoren sofort auswählen, häufig müssen Sie Ihre eigenen Funktionen für die Validierung schreiben.
Fazit
Ich habe die Vuelidate-Bibliothek in vielen Projekten verwendet und bin nie auf unlösbare Probleme gestoßen. Für mich bleibt sie die beste Wahl. Wenn Sie sich für die Größe Ihres Codes interessieren und einen Modellansatz für die Beschreibung von Validierungen bevorzugen - nehmen Sie es, einfache Dokumentation und umfangreiche API ermöglichen die Validierung von Formen beliebiger Komplexität.
Wenn Sie das Admin-Panel für den internen Gebrauch verwenden, möchten Sie keinen einzigen Tropfen Zeit für die Fehlerzeilen aufwenden - wählen Sie vee-validate. Es wird helfen, viele Validierungen schnell und ohne Probleme zu schreiben.
Vielen Dank für Ihre Aufmerksamkeit!