Hola Habr!
La validación de formularios es una de las tareas más importantes en el sitio. Tenemos que validar la presencia de los datos, hacer coincidir el patrón, crear validaciones asincrónicas, aplicar validaciones solo después de eliminar el foco del campo o antes de enviar el formulario ... A veces esto se convierte en un verdadero dolor de cabeza para el desarrollador.
Vue.js contiene muchos enfoques de validación interesantes e inusuales que ayudarán a resolver sus problemas. Descripción general bajo el corte!
TL; DR
Usa
Vuelidate .
Errores comunes
Validaciones HTML5
HTML5 dio a los desarrolladores la capacidad de validar formularios utilizando
nuevos atributos de campo y la API de Validación . Podemos usarlos directamente en nuestras plantillas vue.
Aquí, por ejemplo, hay un formulario de registro simple que consta de tres campos: campos para correo electrónico, para contraseña y reproducción de contraseña. Para los dos primeros, usamos validaciones usando atributos, para el tercero - usando atributos y la API de Validación:
<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 con un ejemploIncluso en un ejemplo tan simple, puede ver muchos problemas:
- Los navegadores solo muestran un error a la vez. El usuario tendrá que intentar enviar el formulario varias veces para ver todos sus errores.
- Los errores se muestran al usuario solo después de intentar enviar el formulario. Para cambiar este comportamiento, tendrá que escribir otra tonelada de código: llame a la función reportValidity () en cada elemento en el evento de desenfoque.
- Para diseñar campos de entrada, solo hay pseudo-clases: válidas y: inválidas, no hay forma de detectar un estado cuando los datos en el campo de entrada son incorrectos, pero el usuario aún no ha interactuado con él.
- Cada navegador muestra errores de validación a su manera, pueden verse feos en su diseño.
- La API de validación en Vue.js es incómoda de usar: debe guardar elementos en $ refs.
Si solo tiene un formulario en el proyecto y solo lo usa usted, la validación HTML5 es una excelente opción. En todos los demás casos, intente utilizar otros enfoques.
Validaciones de biblioteca
Otro problema común que encuentro en los proyectos es la validación de la biblioteca.
<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 con un ejemploNo hay problema con este enfoque. Excepto que en formularios con más de un campo, nace una gran cantidad de código repetido y cada desarrollador escribe validaciones a su manera.
La mejor manera de salir de todos los problemas es usar las bibliotecas que la comunidad nos ofrece. Actualmente hay dos soluciones populares de validación de formularios:
Cada uno tiene su propio enfoque único, que consideraremos en detalle a continuación.
vee-validate
vee-validate: una biblioteca para validaciones que apareció durante la primera versión de Vue.js, tiene una gran comunidad y se utiliza en una gran cantidad de proyectos.
La edad afecta el peso: 31 KB (minificado + GZIP), ¡una vez y media más que el propio Vue.js! Esto se debe al hecho de que la biblioteca contiene inmediatamente un montón de cosas:
- 35 validadores incorporados
- Traducción al inglés de errores
- Directivas de validación
- Componentes de validación
La biblioteca admite 41 idiomas para errores. Para instalarlo y usarlo con la localización deseada, debe realizar solo un par de pasos:
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 tiene dos enfoques para la validación: usar la directiva y usar componentes.
Validación con la directiva v-validate
El enfoque que utiliza la directiva es muy simple: coloca la directiva v-validate en el campo de entrada, al que pasa la lista de validadores. El estado de validación y las líneas de error se pueden obtener de los campos de campos y errores dentro del componente.
Para ver su uso como ejemplo, hagamos una forma simple que:
- Contiene el campo "Serie y número de pasaporte"
- Contiene el campo "Fecha de emisión del pasaporte"
- Contiene el campo "Nombre"
- Agrega el atributo deshabilitado al botón de envío del formulario si los datos son incorrectos
<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 con un ejemploComo puede ver, al usar las banderas dentro de fields.passport_date, tuve que verificar la presencia del campo passport_date: durante la primera representación, vee-validate no tiene información sobre sus campos y, en consecuencia, no hay ningún objeto con banderas. Para deshacerse de esta verificación, use el
asistente especial
mapFields .
Validaciones de componentes
El nuevo método de validación que apareció a fines del año pasado es el uso de componentes. Los propios autores recomiendan usar este enfoque, y va bien con la nueva sintaxis de tragamonedas de Vue.js@2.6.
La biblioteca proporciona dos componentes:
- ValidationProvider: un componente en el que describe las validaciones y en el que ajusta el campo de entrada.
- ValidationObserver: un componente que combina los indicadores de validación de varios ValidationProviders.
Aquí hay un formulario de un ejemplo pasado, pero escrito usando componentes:
<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 con un ejemploOtras características de la biblioteca
Los problemas
El primer y mayor problema es, por supuesto, su tamaño. La biblioteca no admite la agitación de árboles y la adición selectiva de validadores. Te guste o no, tu pandilla siempre tendrá 2 componentes y una directiva de validación, una traducción al inglés y 35 validadores.
El segundo problema se debe al enfoque de suscripción basado en eventos; pueden surgir problemas al integrarse con otras bibliotecas que también cambian el comportamiento de los campos de entrada (máscaras, etc.).
El tercer problema, más subjetivo, es que las traducciones de errores son generales y feas, no reflejan la esencia real.
Toma la forma de ejemplos pasados. Si ingresa el número y la fecha incorrectos del pasaporte, recibirá los siguientes errores:
. dd.MM.yyyy.
Me gustaría reemplazarlos con algo más legible:
1234 567890 ..
Vuelidate
La biblioteca Vuelidate apareció en respuesta a problemas con los enfoques que contiene la biblioteca vee-validate. Vuelidate no tiene controladores de eventos para campos ni traducciones para errores de validación.
Solo requiere una cosa: describir las validaciones en el objeto de validaciones. Luego, ella misma creará un campo calculado $ v con banderas de validación de campo y funciones para cambiar estas banderas.
Gracias a su enfoque de validación simple, Vuelidate pesa solo 3.4 KB (minified + GZIP), casi 10 veces menos que la validación en V.
Se instala con la misma facilidad:
npm i vuelidate
import Vue from 'vue' import Vuelidate from 'vuelidate' Vue.use(Vuelidate)
Reescribe el formulario del ejemplo anterior usando Vuelidate:
<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 con un ejemploLos validadores personalizados pueden describirse rápida y fácilmente mediante funciones. Si desea que sus parámetros de validación caigan en el objeto $ params, use el
asistente especial
withParams .
Como puede ver, los campos con varios errores ocupan mucho espacio y parecen monstruosos: esto se resuelve creando un componente separado para mostrar validaciones.
Otras características de la biblioteca
Los problemas
De los problemas, uno puede seleccionar el número comparativamente escaso de validadores fuera de la caja; a menudo tiene que escribir sus propias funciones para la validación.
Conclusión
Usé la biblioteca Vuelidate en muchos proyectos y nunca he encontrado problemas irresolubles. Para mí, ella sigue siendo la mejor opción. Si le importa el tamaño de su código y prefiere un enfoque modelo para la descripción de las validaciones, tómelo, una documentación simple y una API enriquecida le permitirán validar formas de cualquier complejidad.
Si está utilizando el panel de administración para uso interno, no quiera pasar una sola gota de tiempo en las líneas de error: elija vee-validate. Ayudará a escribir muchas validaciones rápidamente y sin problemas.
Gracias por su atencion!