餓了么的表單控件,如果存在自定義組件更改了值,例如在el-from中存在原生input組件很有可能沒法觸發表單校驗,下拉框或者彈框組件仍然是報紅邊框。
這是因為餓了么的輸入框或者下拉框更改值的時候會自動觸發表單校驗,但是封裝過后的組件無法觸發校驗表單校驗。那么此時可以手動觸發餓了么的表單校驗。
源碼分析
在packages/form/src/form-item.vue中,可以找到addValidateEvents方法,該方法是用來給el-form-item的子組件綁定校驗事件的,如下:
addValidateEvents() {const rules = this.getRules();if (rules.length || this.required !== undefined) {this.$on('el.form.blur', this.onFieldBlur);this.$on('el.form.change', this.onFieldChange);}
}
在packages/input/src/input.vue中,可以找到el-input發送el.form.blur和el.form.change事件的代碼,這里只貼出el.form.change的代碼:
watch: {value(val) {this.$nextTick(this.resizeTextarea);if (this.validateEvent) {this.dispatch('ElFormItem', 'el.form.change', [val]);}}
}
這里用了dispatch方法,該方法的代碼在src/mixins/emitter.js中:
dispatch(componentName, eventName, params) {var parent = this.$parent || this.$root;var name = parent.$options.componentName;while (parent && (!name || name !== componentName)) {parent = parent.$parent;if (parent) {name = parent.$options.componentName;}}if (parent) {parent.$emit.apply(parent, [eventName].concat(params));}
}
由此可以看出,要觸發el-form的校驗,需要el-form-item中的子組件去發布el.form.change或el.form.blur等事件,由el-form-item監聽該事件,觸發表單校驗。
解決方案
方法一:在父頁面中直接調用表單的校驗方法validateField:
watch: {'passwordForm.newPassword': function() {this.$refs.passwordForm.validateField('newPassword')}
}
方法二:在父頁面中發布組件的el.form.change等事件:
<input ref="input" @blur="handleBlur">
<script>
export default {methods: {handleBlur (val) {this.$refs.input.$emit('el.form.blur', val)}}
}
</script>
方法三:在子組件中發布el.form.change等事件,此時無需在父頁面中做任何處理,其中dispatch方法直接將上面所說的emitter.js中的代碼拷貝過來即可:
export default {methods: {dispatch(componentName, eventName, params) {// ... 從emitter.js中拷貝過來的代碼},handleInput (e) {this.$emit('input', e.target.value)this.dispatch('ElFormItem', 'el.form.change', [e.target.value])}}
}
以下是我某項目的解決方法,使用的方法2,即找到el-form-item然后觸發el.form.change事件。
methods: {confirm() {this.$emit("confirm", result);this.$nextTick(() => {parent && parent.$emit("el.form.blur", result); // 重點!觸發表單校驗 el.form.change, el.form.blurparent && parent.$emit("el.form.change", result); // 重點!觸發表單校驗});},},// 找到el-form-item元素的代碼mounted() {let parent = this.$parent;while (parent) { if (parent.$options.name === "ElFormItem") {this.parent = parent;break;}parent = parent.$parent;}
},
原文博客:非el組件/自定義組件觸發el-form的校驗
個人博客: 自定義組件觸發餓了么表單校驗