This article mainly introduces the method of using Async-validator to write Form components, small series feel very good, and now share to everyone, but also for everyone to do a reference. Follow the small series together to see it, hope to help everyone.
In front-end development, the validation of forms is a very common feature, and some UI libraries such as ant.design and element UI implement a form component that has a checksum capability. Async-validator is a library that can perform asynchronous validation of data, and the Form component of Ant.design and Element UI uses Async-validator. This article briefly introduces the basic usage of async-validator and the use of the library to implement a simple verification function of the Form component.
1. Basic usage of Async-validator
The function of the async-validator is to verify that the data is legitimate and to give a hint based on the validation rules.
Here's a demonstration of the most basic usage of async-validator.
Import asyncvalidator from ' async-validator '//Check rule const DESCRIPTOR = {Username: [{ required:true, message: ' Please fill in Write user name '}, { min:3, max:10, message: ' Username length 3-10 '}]}//constructs a validatorconst validator = new Asyncvalida based on the validation rules Tor (descriptor) const DATA = {username: ' username '}validator.validate (model, (errors, fields) = {Console.log (errors )})
When the data does not conform to the validation rules, in the Validator.validate callback function, you can get the corresponding error message.
We can write a custom checksum function to validate the data when the validation rules that are common in async-validator do not meet the requirements. A simple check function is as follows.
function validatedata (rule, value, callback) {Let err if (value = = = ' xxxx ') { err = ' does not conform to spec '} callback (err)}const de Scriptor = {complex: [ { validator:validatedata }]}const validator = new Asyncvalidator (descriptor)
Async-validator supports asynchronous validation of data, so when you write a custom check function, the callback in the checksum function is called, regardless of whether the checksum is passed.
2. Writing Form components and FormItem components
Now that you know how to use async-validator, how do you combine this library with the Form component that you want to write?
Implementation ideas
Describe the implementation idea in a picture.
Form components
The Form component should be a container containing an indefinite number of FormItem or other elements. You can use Vue's built-in slot components to represent the contents of a Form.
The Form component also needs to know how many FormItem components are included that require validation. In general, the communication of a parent-child component is implemented by binding an event on a subassembly, but the slot is used here to not hear the child component's events. This allows you to listen for events through $on on the form component, FormItem the custom events that trigger the Form component before mounting or destroying it.
According to this idea, we first write the Form component.
<template> <form class= "V-form" > <slot></slot> </form> </template><script >import asyncvalidator from ' async-validator ' export default {name: ' V-form ', componentname: ' Vform ',//through $options. Co Mponentname to find the form component data () {return {fields: [],//field: {prop, El}, save FormItem information. Formerror: {}}}, computed: {formrules () {Const DESCRIPTOR = {} This.fields.forEach (({prop}) + = {if (! Array.isarray (This.rules[prop])) {Console.warn (' Prop for ${prop} ' does not exist or its value is not an array ') FormItem] = [{ Required:true}] return} Descriptor[prop] = This.rules[prop]}) return descriptor}, Formvalues () { Return This.fields.reduce ((data, {prop}) = = {Data[prop] = This.model[prop] Return data}, {})}}, methods: { Validate (callback) {Const VALIDATOR = new Asyncvalidator (this.formrules) validator.validate (This.formvalues, (Erro RS) = = {Let Formerror = {} if (Errors && erRors.length) {Errors.foreach (({message, field}) = {Formerror[field] = message})} else {FormEr Ror = {}} this.formerror = Formerror//Let the order of the error messages be the same as the order of the form components const ERRINFO = [] This.fields.forEach ({prop, El}, Index) = {if (Formerror[prop]) {Errinfo.push (Formerror[prop])}}) callback (Errinfo)}) }, Props: {model:object, Rules:object}, created () {this. $on (' Form.addfield ', (field) = {if (field) {T His.fields = [... this.fields, Field]}}) this. $on (' Form.removefield ', (field) = {if (field) {This.fields = This.fields.filter (({prop}) = Prop!== Field.prop)})}}</script>
FormItem components
The FormItem component is much simpler, first to find the Form component that contains it. Next, you can calculate the corresponding error message based on the formerror.
<template> <p class= "Form-item" > <label:for= "prop" class= "Form-item-label" v-if= "label" > {{label}} </label> <p class= "form-item-content" > <slot></slot> </p> </p></template><script>export Default {name: ' Form-item ', computed: { form () { Let parent = the $parent while (parent $options. ComponentName!== ' Vform ') { parent = parent. $parent }< C12/>return parent }, Fielderror () { if (!this.prop) { return ' } const FORMERROR = This.form.formError return Formerror[this.prop] | | "} , props: { prop:string, label:string}}</script>
FormItem also needs to trigger some custom events for the Form component in mounted and Beforedestroy hooks.
<script>export default {//... methods: { dispatchevent (eventName, params) { if (typeof this.form!== ' obj ECT ' &&!this.form $emit) { console.error (' Formitem must be within the form component ') return } this.form. $emit ( EventName, params) }}, mounted () { if (this.prop) { this.dispatchevent (' Form.addfield ', { prop: This.prop, el:this. $el }) }, Beforedestroy () { if (this.prop) { this.dispatchevent (' Form.removefield ', { prop:this.prop }) }}}</script>
Finally, create a new index.js to export the well-written components.
Import Vform from './form.vue ' import FormItem from './formitem.vue ' export {vform, FormItem}
3. How to use
The check function for the form is in the form component. By $ref, you can access the Form component and call the Validate function to obtain the appropriate checksum information.
Here's how to use it:
<template> <v-form:model= "FormData": rules= "Rules" ref= "form" > <form-item label= "phone number" prop= "Tel" > <input type= "Tel" maxlength= "one" v-model.trim= "Formdata.tel"/> </form-item> < Button @click = "Handlesubmit" > Save </button> </v-form></template><script> Import {vform, FormItem} from './common/form ' export default { data () { return { formData: { Tel: ' }, rules: { Tel: [ {required:true, message: ' Your phone number is not entered '}, {pattern:/^1[34578]\d{9}$/, message: ' Your mobile phone number entered incorrectly '}< c13/>]}} , methods: { Handlesubmit () {this . $refs. Form.validate (errs = { Console.log (errs)} )} , Components : { vform, FormItem }}</script >
Click here for the complete code.
4. Summary
This paper introduces briefly the usage of Async-validator, and realizes a Form component with calibration function. There are a lot of deficiencies in the form form that is implemented here: (1) The verification is only available when the form is submitted. (2) The FormItem component should also adjust the UI based on the results of the verification, giving the appropriate hints. Therefore, the Form component is more suitable for use on mobile side with less interaction.
According to the implementation of this idea, according to the application scenario, you can write a custom higher Form component.