您现在的位置是:首页 > 编程语言学习 > 后端编程语言 > 文章正文 后端编程语言

uniapp插件uview下表单无法动态校验的问题解决

2022-12-27 10:14:57 后端编程语言

简介声明:关于uniapp插件uview表单动态校验的一个解决方案1.uview小程序必须用// 如果需要兼容微信小程序,并且校验规则中含有方法等,只能通...

声明:关于uniapp插件uview表单动态校验的一个解决方案

1.uview小程序必须用

// 如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则this.$refs.form1.setRules(this.rules)

2.动态使用,v-for需要放在u-form下的view下面

3.绑定的校验规则rules和表单model下面放置一个同名数组,确保u-form能找到

  1. form: { 
  2.     dynamicAry: [], 
  3. }, 
  4. myrules: { 
  5.     dynamicAry: [] 
  6. }, 
  7. guigerules: { 
  8.     name: [{ 
  9.             required: true
  10.             message: '此为必填字段'
  11.             // blur和change事件触发检验 
  12.             trigger: ['blur''change'], 
  13.         }, 
  14.         { 
  15.             min: 2, 
  16.             max: 12, 
  17.             message: '长度在2-12个字符之间' 
  18.         }, 
  19.     ], 
  20.     price: [{ 
  21.             required: true
  22.             message: '此为必填字段'
  23.             // blur和change事件触发检验 
  24.             trigger: ['blur''change'], 
  25.         }, 
  26.         { 
  27.             validator: (rule, value, callback) => { 
  28.                 return uni.$u.test.amount(value); 
  29.             }, 
  30.             message: '金额格式不对' 
  31.         } 
  32.     ], 
  33.     weight: { 
  34.         type: 'number'
  35.         required: true
  36.         message: '必须是数值'
  37.         trigger: ['change'
  38.     }, 
  39.  
  40.     kucun: { 
  41.         type: 'number'
  42.         required: true
  43.         message: '必须是数值'
  44.         trigger: ['change'
  45.     } 
  46. }, 

4.u-form-item中的表单必须改为 :prop="`dynamicAry.${index}.name`"

5.贴一下代码

  1. <u--form labelPosition="left" :model="form" :rules="myrules" ref="form2"
  2.             <view class="block" v-for=" (item,index) in form.dynamicAry" :key="index"
  3.   
  4.                 <view class="block__title"
  5.                     <text style="flex: 1;">规格信息<text v-if="index>0">{{index}}</text></text> 
  6.                     <view style="width: 60px;" v-if="index>0"
  7.                         <u-button type="error" icon="trash" text="删除"></u-button> 
  8.                     </view> 
  9.   
  10.                 </view> 
  11.                 <view class="block__content"
  12.   
  13.                     <u-form-item required label="规格名称" labelWidth="80" :prop="`dynamicAry.${index}.name`" borderBottom> 
  14.                         <u--input v-model="item.name" border="none" placeholder="请填写规格名称,如200g"></u--input> 
  15.                     </u-form-item> 
  16.                     <u-form-item required label="报价" labelWidth="80" :prop="`dynamicAry.${index}.price`" borderBottom> 
  17.                         <u--input type="digit" :v-model="item.price" border="none" placeholder="请输入商品报价"
  18.                         </u--input> 
  19.                     </u-form-item> 
  20.   
  21.                     <u-form-item required label="重量" labelWidth="80" :prop="`dynamicAry.${index}.weight`" borderBottom> 
  22.                         <u--input type="number" :v-model="item.weight" disabledColor="#ffffff" placeholder="请输入商品重量" 
  23.                             border="none"></u--input> 
  24.                         <text @click="showGuigeWeightUnit(index)">{{item.weightUnit}}</text> 
  25.                         <u-icon slot="right" name="arrow-right"></u-icon> 
  26.                     </u-form-item> 
  27.                     <u-form-item required label="库存" labelWidth="80" :prop="`dynamicAry.${index}.kucun`" borderBottom> 
  28.                         <u--input type="number" :v-model="item.kucun" border="none" placeholder="请输入商品库存"
  29.                         </u--input> 
  30.                     </u-form-item> 
  31.   
  32.                 </view> 
  33.   
  34.             </view> 
  35.         </u--form> 

6.在校验规则中加入触发器 trigger: ['blur', 'change'],比如change,值变动后会触发校验

7.重要的一点,修改uview下的u-form,因为改为数组后,const rule = this.formRules[child.prop];无法找到rule,如 child.prop=‘dynamicAry.0.name’,rule返回的是undefined,uniapp提供一个uni.$u.getProperty可以找到

修改后的validateField函数:

  1. // 对部分表单字段进行校验 
  2. async validateField(value, callback, event = null) { 
  3.     // $nextTick是必须的,否则model的变更,可能会延后于此方法的执行 
  4.     this.$nextTick(() => { 
  5.          
  6.         // 校验错误信息,返回给回调方法,用于存放所有form-item的错误信息 
  7.         const errorsRes = []; 
  8.         // 如果为字符串,转为数组 
  9.         value = [].concat(value); 
  10.         // 历遍children所有子form-item 
  11.         this.children.map((child) => { 
  12.       
  13.             // 用于存放form-item的错误信息 
  14.             const childErrors = []; 
  15.             if (value.includes(child.prop)) { 
  16.                 // 获取对应的属性,通过类似'a.b.c'的形式 
  17.                 const propertyVal = uni.$u.getProperty( 
  18.                     this.model, 
  19.                     child.prop 
  20.                 ); 
  21.                  
  22.                 // 属性链数组 
  23.                 const propertyChain = child.prop.split("."); 
  24.                 const propertyName = 
  25.                     propertyChain[propertyChain.length - 1]; 
  26.                 //修改:将const改为let  
  27.                 let rule = this.formRules[child.prop]; 
  28.                 //修改:链式是无法通过上面的方式获取的,改为下面的方式 
  29.                 if(!rule){ 
  30.                     rule=uni.$u.getProperty( 
  31.                     this.formRules, 
  32.                     child.prop 
  33.                     ); 
  34.                  
  35.                 } 
  36.                 // 如果不存在对应的规则,直接返回,否则校验器会报错 
  37.                 if (!rule) return
  38.                 // rule规则可为数组形式,也可为对象形式,此处拼接成为数组 
  39.                 const rules = [].concat(rule); 
  40.  
  41.                 // 对rules数组进行校验 
  42.                 for (let i = 0; i < rules.length; i++) { 
  43.                     const ruleItem = rules[i]; 
  44.                      
  45.                     // 将u-form-item的触发器转为数组形式 
  46.                     const trigger = [].concat(ruleItem?.trigger); 
  47.                      
  48.                     // 如果是有传入触发事件,但是此form-item却没有配置此触发器的话,不执行校验操作 
  49.                     if (event && !trigger.includes(event)) continue
  50.                     // 实例化校验对象,传入构造规则 
  51.                     const validator = new Schema({ 
  52.                         [propertyName]: ruleItem, 
  53.                     }); 
  54.                          
  55.                     validator.validate({ 
  56.                             [propertyName]: propertyVal, 
  57.                         }, 
  58.                         (errors, fields) => { 
  59.                          
  60.                             if (uni.$u.test.array(errors)) { 
  61.                                 errorsRes.push(...errors); 
  62.                                 childErrors.push(...errors); 
  63.                             } 
  64.                             child.message = 
  65.                                 childErrors[0]?.message ?? null
  66.                         } 
  67.                     ); 
  68.                 } 
  69.             } 
  70.         }); 
  71.         // 执行回调函数 
  72.         typeof callback === "function" && callback(errorsRes); 
  73.     }); 
  74. }, 
  75. // 校验全部数据 

7.动态添加

  1. addGuige() { 
  2.     this.form.dynamicAry.push({ 
  3.         name: ''
  4.         price: ''
  5.         weight: ''
  6.         weightUnit: '克'
  7.         kucun: ''
  8.     }); 
  9.     this.myrules.dynamicAry.push(this.guigerules); 
  10.     // 如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则 
  11.     //微信小程序:动态设置才能生效,每次添加都需要,动态绑定无效 
  12.     this.$refs.form2.setRules(this.myrules) 
  13. }, 

至此,解决完成,折腾了2个小时!!!

这是一个比较简单的解决方案!

补充知识:uView 循环表单校验

uView 默认只能对 model 属性的对象进行校验,对一些包含 列表 的表单来说,无法利用现有的功能实现校验,这里推荐一种简单的方式实现 列表 校验。

实现思路:由于 uniapp 修改源码比较简单,可以直接修改源码添加扩展功能。在 u-form-item 源码中额外添加 prop:target,表示将要校验属性所属的目标对象。

  1. // u-form-item 源码文件中 
  2.  
  3. // 在 props 属性中添加 
  4. target: { 
  5.     type: Object, 
  6. }, 
  7. // 找到 validation 方法 
  8. this.fieldValue = this.target[this.prop]; 
  9. // 修改成如下 
  10. if (this.target) { 
  11.     this.fieldValue = this.target[this.prop]; 
  12. else { 
  13.     this.fieldValue = this.parent.model[this.prop]; 

使用方式,这样即可对列表每一项的 name 属性进行校验

  1. <u-form-item v-for="item in list" prop="name" :target="item"></u-form-item> 

 

相关文章

站点信息