preface
I haven’t written an article for a long time, I have learned some basic components of Webpack, today I bring a tutorial on the form validation component (element.iviewui) (as a vegetables after all experienced many projects can give some novice tips
Github Technical Documentation the technical documentation will be updated continuously
Contents summary
- Principles of interpretation
- Distribution and broadcast // Parent-child interaction
- Async-validator // Form validation plugin introduced
- Form/and API design
- form-item
- input
rendering
1. Principle explanation
consider
So let’s see, we can use forms to trigger validation as a whole or we can use individual input to trigger form-Item validation and if you don’t understand this right now, it’s okay to keep reading.
Distribution and broadcasting
Why broadcast and distribute. In general we try not to use VUEX and BUS (event bus) for components that are not relevant to the business. I send you the code for broadcast and distribution. $emit is sent and broadcast by attaching this.$on(‘event’,res=>()) to the component we want to call.
- Dispatch is to look up and only call 1
- Broadcasts are called down multiple times
- Note that ⚠️ is used for all components
name
- Through mixer
mixins
To use the
Emitters. Js /** * This is called * @param componentName * @param eventName Broadcast (componentName, eventName, This.$children.map(Child =>{if (componentName===child.$options.name) {componentName=== component.$options.name) { child.$emit.apply(child,[eventName].concat(params)) }else { broadcast.apply(child,[componentName,eventName].concat(params)) } }) } export default { methods: @param eventName @param eventName @param Params @param eventName @param Params @param eventName @Param Params @param eventName dispatch(componentName, eventName, params) { let parent = this.$parent || this.$root; Let name = parent.$options.name; // Get the name of the current component instance // Find the current node if the current node has no name and the current name is equal to the name that needs to be passed in // loop out the same component instance of the current name while (parent && (! name||name! ==componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.name; If (parent) {parent.$emit. Apply (parent,[eventName].concat(params))}}, @param eventName / @param eventName / @param Params // Parameters to pass */ broadcast(componentName, eventName, params) { broadcast.call(this,componentName, eventName, params) } } }Copy the code
3.async-validator
If you don’t understand Async-Validator, check out Github
Yarn add Async-validator // -d cannot be added because the plugin needs to be packaged into the projectCopy the code
4. API design
Take a look at the image on Element’s website below
form
There are two injected fields:rules
The rules, and:model
The current form value passesmodel
The value of andrules
Perform a match to verify.form-item
There are two injected fieldslable
andprop
(prop
Come andform
Matches to get the currentform-item
The value of theinput
There’s actually a current@input
Methods.v-model
I won’t explain it
form
- We are in
form
Start by injecting all the current onesform-item
Instance (get) created
Methods that bind and delete the current instance at the beginning of the life cycle. Usually bindings are invoked before the page DOM startsdom
After loadingprovide
Inject uses methods and data that allow child components to call the current parent- The remarks below have been written, which can be safely eaten (it can be verified after testing).
form.vue <template> <form> <slot></slot> </form> </template> <script> export default { name: "AiForm dojo.provide () {/ / / don't understand can look at (https://cn.vuejs.org/v2/api/#provide-inject) return {form: this}}, props: Rules: {type: Object}}, data(){return{fields: Create (){// create (){// create (); this.$on('on-form-item-add',item=>{ if (item) { that.fields.push(item) } }); Some examples of this. / / delete the current $on (' on - form - item - remove 'item = > {the if (item. Prop) {/ / if the current do not prop said current don't delete, because there is no injection) that.fields.splice(that.fields.indexOf(item),1) } }) }, Methods :{/** * resetFields(){// resetFields(){// resetFields(){// resetFields(){// resetFields(); { field.resetField(); }); }, /** * check public method: Return new Promise(resolve=>{/** ** all form-item validates */ let valid = true; // Default is let count = 0; Validation ('',error=>{// Each instance will have validation methods If (error) {valid = false; } // If (++count === this.fields.length) {resolve(valid); if (++count === this.fields.length) {resolve(valid); Then if (typeof callback === 'function') {callback(valid); // Call the injected callback method directly}}}); }); }) } } } </script>Copy the code
5.form-item
form-item
It’s a little bit more complicated and we’ll do it one by oneisRequired
To determine whether it is currently requiredvalidateState
To determine the status of the current checksumvalidateMessage
Current incorrect valueinject: ['form']
We can passthis.from.xxx
To call the event and value of the parent componentcomputed
Under thefieldValue
Maybe it’s changing all the time so we use it by calculating the propertiesinitialValue
The default values we have inmounted
And is currently required to perform verification (prop
Sometimes) will be assignedmixins: [Emitter]
The mixer is the method that’s in there and the date that’s in there and the one that’s used frequently can be in there- we
form-item
Will be introduced toinput
Two methods ofblur
andchange
Input used natively@input
) byform
Incoming checkrules
The inside of thetrigger
To judge
form-item.vue <template> <div> <label :class="isRequired? 'ai-form-item-label-required':''">{{label}}</label> <div> <slot></slot> <div class="ai-form-item-message" v-if="validateState==='error'">{{validateMessage}}</div> </div> </div> </template> <script> import Emitter from '.. /.. /mixins/emitter'; import schema from 'async-validator'; export default { name: "aiFormItem", mixins: [Emitter], inject: ['form'], props: { label: { type: String, default: '' }, prop:{ type: String }, }, computed:{ fieldValue () { return this.form.model[this.prop]; },}, data(){return {initialValue: ", // Save default isRequired: false, // If there is a problem with the current validateState: }}, methods:{/** * binding events required */ setRules(){let that = this; let rules = this.getRules(); If (rules.length) {// every is used to check whether all elements of the array meet the specified criteria (provided by the function) // some returns true this.isrequired = if only one element meets the specified criteria Rules.some (rule=>{// If the current verification rule contains a mandatory item, return rule. })} / * * * * the blur event/enclosing $on (' on - form - the blur, that. OnFieldBlur); $on('on-form-change', that.onfieldchange)}, /** * from the rules attribute of the form, */ getRules () {let that = this; let rules = that.form.rules; rules = rules? rules[that.prop]:[]; Return [] concat (rules | | []) / / this method can make the rules must be}, in the form of an array to form validation * / / * * * the Blur onFieldBlur () {enclosing the validation (' Blur ')}, / / onFieldChange(){this.validation('change')}, */ getFilteredRule (trigger) {let rules = this.getrules (); / /! Return rules.filter(res=>! res.trigger || res.trigger.indexOf(trigger)! = = 1)}, Validation (trigger,callback=function () {}){// blur and change Let rules = this.getFilteredRule(trigger); // Check whether there is a rule if (! Rules | | rules. The length = = = 0) {return} / / set the status to check in / / async - use form of the validator enclosing validateState = 'validating'; var validator = new schema({[this.prop]: rules}); // firstFields: true validates only one validator. Validate ({[this.prop]: this.fieldValue}, {firstFields: true },(errors, fields) => { this.validateState = ! errors ? 'success' : 'error'; this.validateMessage = errors ? errors[0].message : ''; callback(this.validateMessage); }); }, /** * Empty the current form-item */ resetField(){this.form.model[this.prop] = this.initialValue; // Mounted (){// If a prop is not passed, no validation is required. If (this.prop) {this.dispatch('aiForm','on-form-item-add', this); if (this.prop) {this.dispatch('aiForm','on-form-item-add', this); // set the initialValue so that the default value this.initialValue = this.fieldValue is restored on reset; // add forms to validate this.setrules ()}}, // before component destruction, Remove instance from Form cache beforeDestroy(){this.dispatch('iForm', 'on-form-item-remove', this); }, } </script> <style scoped> <! Ai-form-item-label-required :before{content: '*'; color: red; } .ai-form-item-message { color: red; } </style>Copy the code
5.input
value
One input parameter is supported- Because the current is one
input
Injected parameters cannot be placed directlyinput
It’s used inside so it’s assigned todefaultValue
And then usewatch
To keep todefaultValue
Assignment reaches a binding modified by a parent component
<template> <input type="text" @input="handleInput" // change @blur="handleBlur" :value="defaultValue" > </template> <script> import Emitter from '.. /.. /mixins/emitter.js' export default { name: "aiInput", mixins: [Emitter], props: { value: { type: String, default: '' } }, data(){ return { defaultValue: this.value } }, watch:{ value (val) { this.defaultValue = val; }}, Methods :{/** * change event * @param event */ handleInput(event){// Current model assignment this.defaultValue = event.target.value; $emit('input',event.target.value); $emit('input',event.target.value); This. dispatch('aiFormItem','on-form-change',event.target.value)}, $emit('blur',event.target.value); $emit('blur',event.target.value); This. dispatch('aiFormItem','on-form-blur',event.target.value)}}} </script>Copy the code
The last
Finally, give a current available mode of use
<template> <div class="home"> <button @click="changeButton"> </button> <ai-form ref="formItems" :model="formValidate" :rules="ruleValidate"> <ai-form-item label=" user name" prop="name"> < AI-input v-model=" formvalidate. name"/> </ai-form-item> </ai-form> </div> </template> <script> import AiForm from ".. /components/form/form"; import AiFormItem from ".. /components/form/form-item"; import AiInput from ".. /components/input/ai-input"; export default { name: 'home', components: {AiInput, AiFormItem, AiForm},], data(){ return{ formValidate: { name: '123z', mail: "}, ruleValidate: {name: [{required: true, message: 'user name cannot be empty ', trigger: 'blur' }, ], } } }, Methods: {changeButton () {this. $refs. FormItems. ResetFields method () / / clear this. $refs. FormItems. The validate () / / verification method .then(res=>{ console.log(res) }) } }, } </script>Copy the code
summary
May now small partners still do not understand. As the saying goes. Master led the door, practice in the individual. There are enough notes in the code. If you still don’t know, you can ask your friends,
Seek to rely on the spectrum push (Beijing area) can leave a message I +. =