上一部分總結了基礎常用的js表單校驗,包括原生以及框架,下面來總結這一個月涉及到的動態校驗:
動態表單校驗大致分為三種情況:
1. 首先是固定校驗規則,但是表單元件是動態生成的,例如:在表單或者表格裡有“增加”功能,增加一行,給新生成的表單元件新增校驗規則。
2. 第二類就是元件固定,但是校驗規則會隨著其他條件的變化而變化,例如:基本的最常見的例子是確認密碼的校驗,判斷第二次輸入的密碼與第一次輸入是否一致。
3. 最後,比較複雜的就是以上兩類情況的混合情況,動態生成的表單,且校驗規則也是動態變化的。
接下來還是用最直觀的舉例子來解釋用法:
這裡使用了element自帶的rules,其他框架同理,也可以自己繫結方法,原生的用blur,focus等也可以
一:固定校驗規則+元件動態生成
要實現的效果:點選第一行的新增生成下面的表格,表格各自校驗
實現方法程式碼舉例:
html :(放到表格裡的元件,和表單同理)
1 <el-table-column align="center" label="金額標準" prop="level"> 2 <template slot-scope="scope"> 3 <span v-if="scope.row.edit">{{ scope.row.level}}</span> 4 <el-form-item v-show="!scope.row.edit" :prop="'list.'+scope.$index+'.level'" :rules="rules.level"> 5 <el-input v-model="scope.row.level" autofocus placeholder="請輸入金額標準"></el-input> 6 </el-form-item> 7 </template> 8 </el-table-column>
js :(校驗規則以及觸發方式定義)
1 data() { 2 return { 3 rules:{ 4 level: [ 5 {required: true, message: '請輸入金額標準', trigger: ['blur', 'change']}, 6 { validator:function(rule,value,callback){ 7 if(/^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(Number(value)) == false||Number(value)>10000){ 8 callback(new Error("請輸入數字,可保留兩位小數,最大不超過10000")); 9 }else if(/^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/.test(Number(value)) == false){ 10 callback(new Error("請輸入數字,可保留兩位小數,最大不超過10000")); 11 }else{ 12 callback(); 13 } 14 }, trigger:['blur', 'change'] 15 }], 17 } 18 } 19 }
js:(實現方式)
1 formValidate(formName){ 2 this.$refs[formName].validate((valid) => { 3 if(valid) { 4 this.validateForm=true; 5 }else{ 6 this.$message.warning("請確認輸入資訊無誤!"); 7 this.validateForm=false; 8 } 9 }); 10 return this.validateForm; 11 }
呼叫formValidate方法即可。
二:固定元件+動態校驗規則
要實現的效果:(element官方舉例)
實現方法程式碼舉例:
html:
1 <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm"> 2 <el-form-item label="密碼" prop="pass"> 3 <el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input> 4 </el-form-item> 5 <el-form-item label="確認密碼" prop="checkPass"> 6 <el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input> 7 </el-form-item> 8 </el-form>
js:(校驗規則可以定義到return之前,也可以直接放到rules裡)
1 data() { 2 var validatePass = (rule, value, callback) => { 3 if (value === '') { 4 callback(new Error('請輸入密碼')); 5 } else { 6 if (this.ruleForm.checkPass !== '') { 7 this.$refs.ruleForm.validateField('checkPass'); 8 } 9 callback(); 10 } 11 }; 12 var validatePass2 = (rule, value, callback) => { 13 if (value === '') { 14 callback(new Error('請再次輸入密碼')); 15 } else if (value !== this.ruleForm.pass) { 16 callback(new Error('兩次輸入密碼不一致!')); 17 } else { 18 callback(); 19 } 20 }; 21 return { 22 ruleForm: { 23 pass: '', 24 checkPass: '' 25 }, 26 rules: { 27 pass: [ 28 { validator: validatePass, trigger: 'blur' } 29 ], 30 checkPass: [ 31 { validator: validatePass2, trigger: 'blur' } 32 ] 33 } 34 };
三:動態生成元件+動態校驗規則
要實現的效果:三個元件分別縱向對比校驗,各元件個數不固定,為動態生成,各自校驗規則也相互影響,人數2依附於人數1的輸入值。
實現方法程式碼舉例:
html:(繫結prop以及rules)
1<tr> 2 <td> 3 <div> 4 <div><label class="col-sm-4 control-label addbefore">天數</label></div> 6 </div> 7 </td> 8 <td> 9 <div> 10 <template v-for="(item, index) in form.list1"> 11 <el-form-item 12 :key="item.key" 13 :id="item.key" 14 :name="item.key" 15 style="float: left;" 16 :prop="'list1.' + index +'.a_value'" 17 :rules="rules.a_value1"> 18 <el-input v-model.number="item.a_value"></el-input><span>天</span> 20 </el-form-item> 21 </template> 22 </div> 23 </td> 24 </tr> 25<tr> 26 <td> 27 <div><label>人數1</label></div> 30 </td> 31 <td> 32 <div> 33 <template v-for="(domain, index) in form.list2"> 34 <el-form-item 35 :key="domain.key" 36 :id="domain.key" 37 :name="domain.value" 38 style="float: left;" 39 :prop="'list2.' + index +'.b_value'" 40 :rules="rules.b_value"> 41 <el-input v-model.number="domain.b_value"></el-input><span>人</span> 43 </el-form-item> 44 </template> 45 </div> 46 </td> 47</tr> 48<tr> 49 <td> 50 <div><label>人數2</label></div> 56 </td> 57 <td> 58 <div> 59 <template v-for="(domain, index) in form.list3"> 60 <el-form-item 61 :key="domain.key" 62 :id="domain.key" 63 :name="domain.value" 64 style="float: left;" 65 :prop="'list3.' + index +'.c_value'" 66 :rules="rules.c_value"> 67 <el-input v-model.number="domain.c_value"></el-input><span>人</span> 69 </el-form-item> 70 </template> 71 </div> 72 </td> 73</tr>
js :(資料及校驗規則定義)
1 data(){ 2 var me=this 3 return { 4 form:{ 5 list1:[], 6 list2:[], 7 list3:[] 8 } 9 rlues:{ 10 a_value: [ 11 { required: true, message: '請輸入', trigger: ['blur', 'change'] }, 12 { type: 'number', message: '請輸入數字', trigger: ['blur', 'change']}, 13 { 14 validator: (rule, value, callback) => { 15 if (value > 200) { 16 callback(new Error('天數應小於200')) 17 } else { 18 callback() 19 } 20 }, 21 trigger: ['blur', 'change'] 22 } 23 ], 24 b_value:[ 25 { required: true, message: '請輸入', trigger: ['blur', 'change'] }, 26 { type: 'number', message: '請輸入數字', trigger: ['blur', 'change']}, 27 { 28 validator: (rule, value, callback) => { 29 if (value > 100) { 30 callback(new Error('人數1應小於100')) 31 } else { 32 callback() 33 } 34 }, 35 trigger: ['blur', 'change'] 36 } 37 ], 38 c_value:[ 39 { required: true, message: '請輸入', trigger: ['blur', 'change'] }, 40 { type: 'number', message: '請輸入數字', trigger: ['blur', 'change']}, 41 { 42 validator: (rule, value, callback) => { 43 let index=Number(rule.field.substr(6, 1)) 44 let sc=(me.form.list2[index].b_value)*0.1 45 if (value > sc) { 46 callback(new Error('人數2不超過人數1的10%')) 47 } else { 48 callback() 49 } 50 }, 51 trigger: ['blur', 'change'] 52 } 53 ] 54 } 55 } 56 }
js:(實現方式)
1 formValidate(formName){ 2 this.$refs[formName].validate((valid) => { 3 if(valid) { 4 this.validateForm=true; 5 }else{ 6 this.$message.warning("請確認輸入資訊無誤!"); 7 this.validateForm=false; 8 } 9 }); 10 return this.validateForm; 11}
總結:
這三種情況其實基本原理是相同的,即是在變化的元素以及變化的標準怎麼比較,首先來說確定兩點,一是要繫結prop,動態雙向繫結,相當於生成元件是時給該元素生成一個標識,一般來說動態繫結寫法如下:
:prop="'list.' + index +'.value'"
或者寫成
:prop="'list.'+scope.$index+'.value'"
其次,是繫結一個規則:
:rules="rules.value"
然後就是具體校驗,可以寫到html裡,也可以寫到js裡,一般來說有校驗方法的寫到js裡,需要注意的是 validator: (rule, value, callback) => { },這個回撥方法裡的三個引數:
第一個引數 rule,為繫結元素的prop,主要用來取到需要進行比較的值,即規則;
第二個引數 value,為此時輸入的內容,和規則作比較,是否符合;
第三個引數 callback,為校驗完的回撥函式,校驗成功或失敗的提示在callback函式中執行;
以上為動態校驗總結。
這兩篇內容詳細記錄了我遇到的,以及所有能想到的前端校驗的情況的相關內容,歡迎補充。