问题:当弹出新增/编辑弹窗的时候,没有点确定按钮也进行了必填校验
一般我们遇到这种问题都是直接使用clearValidate进行清除校验,我在打开弹窗和关闭弹窗的时候都对其进行了清除校验,还是会触发。然后我发现当注释掉form表单赋空值相关语句就不会触发了。
下面我们从框架源码角度分析一下是怎么触发的。
form.vue
// 表单校验 参数是一个回调函数 (valid, invalidFields)
validate(callback) {
if (!this.model) {
console.warn('[Element Warn][Form]model is required for validate to work!');
return;
}
let promise;
// 如果没有回调函数,则返回promise
if (typeof callback !== 'function' && window.Promise) {
promise = new window.Promise((resolve, reject) => {
callback = function (valid, invalidFields) {
valid ? resolve(valid) : reject(invalidFields);
};
});
}
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;
}
},
上面的代码是form表单的校验方法,通过看源码发现,表单校验实际是循环校验每一个表单项。接下来我们查看form-item组件的校验触发时机。
// 输入框失焦 触发校验
onFieldBlur() {
this.validate('blur');
},
// 输入框改变(model对象的属性值发生变化也会触发) 触发校验
onFieldChange() {
console.log('触发了onFieldChange');
if (this.validateDisabled) {
this.validateDisabled = false;
return;
}
this.validate('change');
},
通过查看代码发现,在onFieldBlur函数和onFieldChange函数中有调用validate校验方法。
// 添加校验事件
addValidateEvents() {
// 获取校验规则
const rules = this.getRules();
if (rules.length || this.required !== undefined) {
// 监听form的blur 和 change事件
this.$on('el.form.blur', this.onFieldBlur);
this.$on('el.form.change', this.onFieldChange);
}
},
而这两个方法是作为el.form.blur和el.form.change监听的回调函数。 那么只要我们找到在哪里触发这两个监听函数不就找到了吗? form-item组件下面都是一些input、select、checkbox等表单元素,要对form-item进行校验就需要获取input等表单元素的值,以这个为切入点,我们以input为例,看看input源码。
watch: {
value(val) {
this.$nextTick(this.resizeTextarea);
if (this.validateEvent) {
this.dispatch('ElFormItem', 'el.form.change', [val]);
}
},
}
在input组件源码我们发现,该组件对input的值(value)进行了监听,变化触发el.form.change监听,然后执行onFieldChange回调,进行校验,这里的dispatch是用于找到目标父节点(ElFormItem),并触发(el.form.change)监听,带上val参数。
总结
因为我定义的表单属性初始值是空字符串,而后台返回的数据为null, 赋值的时候触发了change监听,进而进行了校验。我们需要保证赋空值的时候需要和初始值保持一致,或者判断一下后台返回的是空值的时候,不进行赋值。