vue表单验证你真的会了吗?vue表单验证
(form)validate
前⾔
很久没有写⽂章了,学习了⼀下webpack,基础的⼀些组件,今天带来form表单验证组件(element.iviewui)的⼀期教程(作为⼀个菜鸡毕竟经历众多项⽬可以给⼀些新⼿⼀点提⽰(QQ技术讨论)838293023备注(github进来的
技术⽂档会持续更新
效果图
1.原理解释
考虑
我们看⼀下我们可以⽤form去整体触发校验也可以单个input来触发form-item 进⾏校验童鞋们现在可能感觉还是没懂,没关系继续往下看。
2.派发和⼴播
为什么要⽤⼴播和派发呢。通常我们和业务没有关系的组件尽量不要使⽤vuex和bus(事件总线)。下⾯我送上⼴播和派发的代码。我们在需要调⽤组件绑上this.$on('event',res=>()),通过派发和⼴播进⾏调⽤$emit。
派发是向上查且只调⽤1个
⼴播是向下查调⽤多个
注意⚠ 所有的组件都要写上name
通过混合器 mixins 来使⽤
emitter.js
/**
* 递归使⽤ call ⽅式this指向
* @param componentName // 需要的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
function broadcast(componentName, eventName, params) {
// 循环⼦节点到名称⼀样的⼦节点否则递归当前⼦节点
this.$children.map(child=>{
if (componentName===child.$options.name) {
child.$emit.apply(child,[eventName].concat(params))
}else {
broadcast.apply(child,[componentName,eventName].concat(params))
}
})
}
export default {
methods: {
/**
* 派发 (向上查) (⼀个)
* @param componentName // 需要的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;//$parent 到最近的⽗节点 $root 根节点
let name = parent.$options.name; // 获取当前组件实例的name
// 如果当前有节点 && 当前没名称且当前名称等于需要传进来的名称的时候就去查当前的节点
/
/ 循环出当前名称的⼀样的组件实例
while (parent && (!name||name!==componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
// 有节点表⽰当前到了name⼀样的实例
if (parent) {
parent.$emit.apply(parent,[eventName].concat(params))
}
},
/**
* ⼴播 (向下查) (⼴播多个)
* @param componentName // 需要的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
broadcast(componentName, eventName, params) {
broadcast.call(this,componentName, eventName, params)
}
}
}
3.async-validator
不懂async-validator可以去官⽹看看
yarn add async-validator // 因为当前这个插件是需要打包到项⽬⾥的所以不能加-D
4.api设计
我们看⼀下下⾯element官⽹的图`
form有2个注⼊的字段:rules规则,和:model当前form的值会通过model的值和rules进⾏匹配来进⾏校验. form-item有2个注⼊的字段lable和prop ( prop )是来和form进⾏匹配来获取当前的form-item的值的
input其实有当前的@input的⽅法。v-model就不解释了
form
我们在form先开始注⼊当前所有的form-item实例(获取)
created会在⽣命周期开始的时候绑定和删除当前实例的⽅法。通常绑定都在页⾯dom开始前调⽤需要在dom加载完provide配合inject 使⽤让⼦组件可以调⽤当前⽗组件的⽅法以及data
下⾯都写了备注可以放⼼⾷⽤(经过测试当前是可以进⾏校验的)
form.vue
<template>
<form>
<slot></slot>
</form>
</template>
<script>
export default {
name: "aiForm",
provide(){ // [不懂的可以看看](/v2/api/#provide-inject)
return {
form: this
}
},
props: {
// 当前 form 的model
model: {
type: Object
},
// 验证
rules: {
type: Object
}
},
data(){
return{
fields: [] // 储存当前的 form-item的实例
}
},
created(){
// 存当前实例
let that =this;
this.$on('on-form-item-add',item=>{
if (item) {
that.fields.push(item)
}
});
// 删除当前有的实例
this.$on('on-form-item-remove',item=>{
if (item.prop) {// 如果当前没有prop的话表⽰当前不要进⾏删除(因为没有注⼊)
that.fields.splice(that.fields.indexOf(item),1)
}
})
},
methods:{
/**
* 清空
*/
resetFields(){//添加resetFields⽅法使⽤的时候调⽤即可
/**
* 当前所有当form-item 进⾏赋值
*/
this.fields.forEach(field => {
});
},
/**
* 校验公开⽅法:全部校验数据,⽀持 Promise
*/
validate(callback){
return new Promise(resolve=>{
/**
* 当前所有当form-item 进⾏校验
*/
let valid = true; // 默认是通过
let count = 0; // 来匹配当前是否是全部检查完
this.fields.forEach(field => {
// 每个实例都会有 validation 的校验的⽅法
field.validation('',error=>{
// 只要有⼀个不符合那么当前的校验就是未通过的
if (error) {
valid = false;
}
// 通过当前检查完所有的form-item的时候才会调⽤
if (++count === this.fields.length) {
resolve(valid);// ⽅法使⽤then
if (typeof callback === 'function') {
callback(valid);// 直接调⽤注⼊的回调⽅法
}
}
});
});
})
}
}
}
</script>
5.form-item
form-item⽐较复杂我们⼀个⼀个讲
isRequired来判断当前是否需要必填
validateState来判断当前校验的状态
validateMessage当前的错误的值
inject: ['form'] 我们就可以通过来调⽤⽗组件的事件以及值了
computed下的fieldValue可能在不停的变化所以我们通过计算属性来使⽤
initialValue 默认的值我们在mounted的时候且当前需要进⾏校验的时候(prop有的时候)会赋值
mixins: [Emitter]混合器就是⾥⾯的⽅法以及date都可以在当前调⽤使⽤频繁的都可以放在混合器⾥⾯
我们form-item 会传⼊input的两个⽅法blur和change(input原⽣使⽤的@input)通过form传⼊的校验rules⾥⾯的trigger来判断
form-item.vue
<template>
<div>
<label :class="isRequired?'ai-form-item-label-required':''">{{label}}</label>
<div>
valid from是什么意思<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 del[this.prop];
},
},
data(){
return {
initialValue: '', // 储存默认值
isRequired: false, // 当前的是否有问题
validateState: '', // 是否校验成功
validateMessage: '', // 校验失败⽂案
}
},
methods:{
/**
* 绑定事件进⾏是否 required 校验
*/
setRules(){
let that = this;
let rules = Rules();//拿到⽗组件过滤后当前需要使⽤的规则
if (rules.length) {
// every ⽅法⽤于检测数组所有元素是否都符合指定条件(通过函数提供)
// some 只要有⼀个符合就返回true
this.isRequired = rules.some(rule=>{
// 如果当前校验规则中有必填项,则标记出来
quired;
})
}
/**
* blur 事件
*/
this.$on('on-form-blur',FieldBlur);
/**
* change 事件
*/
this.$on('on-form-change',FieldChange)
},
/**
* 从 Form 的 rules 属性中,获取当前 FormItem 的校验规则
*/
getRules () {
let that = this;
let rules = that.form.rules;
rules = rules?rules[that.prop]:[];
return [].concat(rules||[])//这种写法可以让规则肯定是⼀个数组的形式
},
/**
* Blur 进⾏表单验证
*/
onFieldBlur(){
this.validation('blur')
},
/**
* change 进⾏表单验证
*/
onFieldChange(){
this.validation('change')
},
/**
* 只⽀持 blur 和 change,所以过滤出符合要求的 rule 规则
*/
getFilteredRule (trigger) {
let rules = Rules();
// !igger 没有调⽤⽅式的时候默认就校验的
/
/ filter 过滤出当前需要的规则
return rules.filter(res=>!igger || igger.indexOf(trigger)!==-1)
},
/**
* 校验数据
* @param trigger 校验类型
* @param callback 回调函数
*/
validation(trigger,callback=function () {}){
// blur 和 change 是否有当前⽅式的规则
let rules = FilteredRule(trigger);
/
/ 判断当前是否有规则
if (!rules || rules.length === 0) {
return
}
// 设置状态为校验中
// async-validator的使⽤形式
this.validateState = 'validating';
var validator = new schema({[this.prop]: rules});
// firstFields: true 只会校验⼀个
validator.validate({[this.prop]: this.fieldValue}, { firstFields: true },(errors, fields) => {    this.validateState = !errors ? 'success' : 'error';
this.validateMessage = errors ? errors[0].message : '';
callback(this.validateMessage);
});

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。