公司的系統中,產品經理在設計時常常要求對某個字段進行區間閾值設置或者做爲篩選條件。可是苦於element中沒有很是契合的組件(slider組件並不支持兩端均能設定),因而本身動手造了一個。javascript
最終的展現效果以下:html
這裏以項目的需求爲例,基本的需求以下:前端
頁面和表單校驗結構同樣:java
<el-form ref="form" :model="form" :rules="rules"> <el-form-item prop="min"> <el-input v-model="form.min" /> </el-form-item> ~ <el-form-item prop="max"> <el-input v-model="form.max" /> </el-form-item> </el-form>
根據上面的思路,單個表單的校驗屬於公共校驗方法,關聯校驗須要分別校驗(由於對比對象不一樣,且提示語不一樣),由此在自定義校驗中有了以下定義:segmentfault
rules: { min: [ { required: true, message: '必填項,請維護', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMin, trigger: 'blur' }, ], max: [ { required: true, message: '必填項,請維護', trigger: 'blur' }, { validator: this.validateCom, trigger: 'blur' }, { validator: this.validateMax, trigger: 'blur' }, ], },
公共校驗方法:正整數校驗、區間校驗promise
validateCom(rule, value, callback) { const one = Number(value); if (Number.isInteger(one)) { if (one < MIN_NUMBER) { return callback(new Error(`輸入值必須大於${MIN_NUMBER}`)); } else if (one > MAX_NUMBER) { return callback(new Error(`輸入值必須小於${MAX_NUMBER}`)); } return callback(); } return callback(new Error('輸入值必須爲正整數')); },
注意:input輸出的始終是字符串類型,須要轉換成數字後進行比對前端工程師
關聯校驗:ide
validateMin(rule, value, callback) { const one = Number(value); const max = Number(this.form.max); if (!max || one < max) { return callback(); } return callback(new Error('輸入值不得大於最大閾值')); }, validateMax(rule, value, callback) { const one = Number(value); const min = Number(this.form.min); if (!min || one > min) { return callback(); } return callback(new Error('輸入值不得小於最小閾值')); },
大概,你會想,這不就完了嗎!so easy!如今真正的坑纔開始ui
根據上面的寫法,組件的基本功能實現了,可是有一個坑!以下:this
很顯然,左側值是小於右側值的,可是校驗提示仍然報錯。究其緣由,仍是關聯校驗的問題。既然是關聯交驗,改變其中一個時應該會從新校驗兩個。很簡單,在input改變時,從新校驗表單不就OK了嗎
handleChange() { this.$refs.form.validate(); }
真實表現正如咱們所料,可是當咱們打開console的時候,會看到Uncaught (in promise) false
,這又是什麼鬼,身爲優秀的前端工程師,你定不會容許本身的代碼裏報錯,即便不影響正常流程。
經查證:Promise報錯,Uncaught的意思是表明有reject狀態沒有被catch。究其緣由,改變一個值時,校驗整個表單時,改變的那個input會執行兩次校驗,致使異常。
最後作以下修改:
handleMinChange() { this.$refs.form.validateField('max'); }, handleMaxChange() { this.$refs.form.validateField('min'); }, // 並對外暴露操做方法 getFormData() { const ret = {}; this.$refs.form.validate((valid) => { ret.valid = valid; ret.form = this.form; }); return ret; }, resetForm() { this.$refs.form.resetFields(); },
type=number