表單時你們經常使用的,根據本站的百度統計後臺顯示來到道招網的程序不少都在關注《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時,才表示校驗成功。這樣是沒錯,可是若是你的項目是分多個表單,而且須要幾個表單都校驗經過才能提交,你是否是以爲不那麼好寫了。 其實官方已經給出了說明了 數組
只是說就差給個demo了,畢竟部分初學者喜歡複製而後修改嘛。 咱們根據上面的源碼能夠看出想使用校驗,必須傳遞model屬性。若是傳遞的callback不是方法的話,會定義一個promise,同時會定義callback爲方法,參數依然是是否校驗經過的結果。我的以爲這樣仍是很巧妙的,畢竟**後面就能夠徹底按照傳遞了callback爲前提繼續寫了,中途不用來回想若是用戶是傳遞callback的模式呢仍是直接使用promise的模式了,只是說最後發現若是有promise就返回便可。**點個贊。 接着看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