表单时你们经常使用的,根据本站的百度统计后台显示来到道招网的程序不少都在关注《element-ui动态表单async-validate校验 please transfer a valid prop path to form item!》 看来不少网友对element-ui的校验(或者说是async-validator)使用不太熟悉,想了想仍是有必要分享下element-ui的表单校验机制的。javascript
首先表单校验分el-form, el-form-item以及里面的el-input, el-select等。 这里就以el-form, el-form-item和el-input组合为例。为了讲的更加详细,决定分一个系列来说。毕竟码字多了就想草草结束。。。 先直接看el-form吧,这里的代码不多,毕竟主要内容是以slot插入的。html
<template>
<form class="el-form" :class="[ labelPosition ? 'el-form--label-' + labelPosition : '', { 'el-form--inline': inline } ]">
<slot></slot>
</form>
</template>
复制代码
属性就很少说了,跟校验相关的就是model和rules。还有就是validateOnRuleChange
,它默认是true
,而且有这样的watch存在vue
watch: {
rules() {
if (this.validateOnRuleChange) {
this.validate(() => {});
}
}
},
复制代码
默认规则改变会实时校验表单哦。java
// 表单校验源码
validate(callback) {
if (!this.model) {
console.warn('[Element Warn][Form]model is required for validate to work!');
return;
}
let promise;
// if no callback, return promise
if (typeof callback !== 'function' && window.Promise) {
promise = new window.Promise((resolve, reject) => {
callback = function(valid) {
valid ? resolve(valid) : reject(valid);
};
});
}
let valid = true;
let count = 0;
// 若是须要验证的fields为空,调用验证时马上返回callback
if (this.fields.length === 0 && callback) {
callback(true);
}
let invalidFields = {};
this.fields.forEach(field => {
field.validate('', (message, field) => {
if (message) {
valid = false;
}
invalidFields = objectAssign({}, invalidFields, field);
if (typeof callback === 'function' && ++count === this.fields.length) {
callback(valid, invalidFields);
}
});
});
if (promise) {
return promise;
}
},
复制代码
官网的示例是这样的element-ui
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
复制代码
因此不少初学者是否是一直在用callback的方式啊,里面的参数为true时,才表示校验成功。这样是没错,可是若是你的项目是分多个表单,而且须要几个表单都校验经过才能提交,你是否是以为不那么好写了。 其实官方已经给出了说明了 数组
this.fields
,这是个数组,存储了哪些
el-form-item
是须要校验的。在
created
时进行存储的。 由于vue的父组件的
created
周期是在子组件的
created
以前的。
// el-form源码
created() {
this.$on('el.form.addField', (field) => {
if (field) {
this.fields.push(field);
}
});
/* istanbul ignore next */
this.$on('el.form.removeField', (field) => {
if (field.prop) {
this.fields.splice(this.fields.indexOf(field), 1);
}
});
},
复制代码
里面同时监听了移除校验某个el-form-item
的事件。 到此el-form源码里面剩下的就很少了。只剩下如下三个方法了,放一块儿吧。promise
// el-form源码
resetFields() {
if (!this.model) {
process.env.NODE_ENV !== 'production' &&
console.warn('[Element Warn][Form]model is required for resetFields to work.');
return;
}
this.fields.forEach(field => {
field.resetField();
});
},
clearValidate(props = []) {
const fields = props.length
? (typeof props === 'string'
? this.fields.filter(field => props === field.prop)
: this.fields.filter(field => props.indexOf(field.prop) > -1)
) : this.fields;
fields.forEach(field => {
field.clearValidate();
});
},
validateField(prop, cb) {
let field = this.fields.filter(field => field.prop === prop)[0];
if (!field) { throw new Error('must call validateField with valid prop string!'); }
field.validate('', cb);
}
复制代码
分别是重置表单、清空校验、单独校验某个el-form-item
。async
须要说明下的是: 这里的field.validate
须要在el-form-item
里面看了。 el-form经过下面的方式实现了在它的子组件里面可以经过this.elForm
来访问el-form
的功能。Vue2.2.0+的功能ide
// el-form源码
provide() {
return {
elForm: this
};
},
复制代码
el-form的源码应该是讲的很清楚了,有须要的同窗能够查看源码。ui