uniapp动态表单校验 深层对象表单校验 表单不会自动校验 校验第二次失效

文章介绍了在uni-app框架下处理动态表单校验的方法,特别是在微信小程序中遇到的问题及解决方案。作者通过使用v-for循环动态生成表单,并结合uni-forms和uni-easyinput组件,利用blur和input事件进行自定义校验。同时,针对不同平台的兼容性问题,如自定义校验规则在微信小程序端的处理,文中给出了具体的代码示例和解决策略。
摘要由CSDN通过智能技术生成

日常开发中 表单提交功能很常见 但是并不是所有表单都是简单的一层 有时候我们会有这种场景:

大表单中有一个按钮,点击按钮在大表单中增加一个小表单,这就是动态表单

如何校验这种动态表单呢,网上查找很多博客 都不是很满意 以下是我的解决方案

1.首先是页面

<uni-forms :border="true" ref="form" :rules="rules" :model="formData">
        <uni-forms-item label="xxx" required name="xxx">
          <uni-easyinput :trim="true" :inputBorder="false" v-model="formData.xxx" 
          placeholder="请输入xxx" />
        </uni-forms-item>


      <!-- 动态表单区域 -->
      <view v-for="(item, index) in formData.xxx" :key="index">
      
      <!-- 注意下面的 name="'xxx'+index" 其中xxx是this.formDate.xxx[index].xxx属性 
           name必须对应rules的属性名
       -->
       
        <uni-forms-item label="文字文字" required type="number" :name="'xxx'+index">
          <uni-easyinput @blur="blurSj" @input="inputSjchange" 
          :inputBorder="false"
           v-model="formData.rule[index]['xxx']" placeholder="请输入xxx" />
           
        </uni-forms-item>
           <uni-forms-item label="文字文字1" required type="number" :name="'xxx1'+index">
          <uni-easyinput @blur="blurSj1" @input="inputSjchange1" 
          :inputBorder="false"
           v-model="formData.rule[index]['xxx1']" placeholder="请输入xxx1" />
        </uni-forms-item>
 
    </uni-forms>
    <view class="addbtn"><text @tap="add">+ 添加动态表单</text></view>
    <view @click="submit('submit')"> 保存 </view>

2.其次是逻辑

<script>
  export default {
    name: "",
    data() {
      return {
        id:'',
        formData: {
          'xxx':'',
          'xxx': {
          'Dtarr': [
              {
                'xxx':'',
                'xxx1':''
              }
            ],
          }
        },
        // 校验规则
        rules: {
         // 这是动态表单的校验
          xxx: {
            rules: [{
                required: true,
                errorMessage: '请输入xxx',
                trigger: 'blur'
              },
              // 这是自定义表单输入的格式校验 此自定义校验规则在h5中没问题 微信小程序端不生效
              // 所以我在 uni-easyinput标签上绑定了 @blur="blurSj"
              //用于微信小程序端的格式校验 我这里写的是输入正整数或者两位正浮点数
              {
                validateFunction: (rule, value, data, callback) => {
                  let isInteger = /^\+?[1-9][0-9]*$/
                  let legal = isInteger.test(Number(value))
                  if (!legal) {
                    callback('请填写正确的件数格式')
                  }
                  return true
                }
              },
            ]
          },
          xxx1: {
            rules: [{
              required: true,
              errorMessage: '请输入xxx1',
              trigger: 'blur'
            }, {
              validateFunction: (rule, value, data, callback) => {
                let isInteger = /^\+?[1-9][0-9]*$/
                let isPosflopoinum = /^(([1-9]\d*)(\.\d{1,2})?)$|(0\.0?([1-9]\d?))$/
                let legal = isInteger.test(Number(value)) || isPosflopoinum.test(Number(value))
                if (!legal) {
                  callback('请填写正确的运费格式')
                }
                return true
              }
            }]
          },
        },
        isInteger: /^\+?[1-9][0-9]*$/, // 正则 只能输入正整数
        isPosflopoinum: /^(([1-9]\d*)(\.\d{1,2})?)$|(0\.0?([1-9]\d?))$/, // 正则 只能输入正两位浮点数
      }
    },

    onReady() {
      this.getTransportList() // 在编辑的时候为了也有验证规则这个函数也必须写在onready生命周期中,亲测必须这样
      this.$refs.form.setRules(this.rules); // 必须在onready生命周期中设置校验规则
    },

    methods: {
    // 这就是微信小程序端不能使用自定义校验规则,那就直接在失去焦点时判断输入的正确与否
    // 不正确直接置空
      blurSj(e) {
        for (let key in this.formData.Dtarr) {
          let legal = this.isInteger.test(Number(this.formData.rule[key].snum))
          if (!legal) {
            this.formData.rule[key].xxx= ''
          }
        }
      },
      blurSj1(e) {
        for (let key in this.formData.Dtarr) {
          let legal = this.isInteger.test(Number(this.formData.rule[key].snum))
          if (!legal) {
            this.formData.rule[key].xxx1= ''
          }
        }
      },
      // 这就是uniapp的框架不会自动校验是否有值 造成明明已经填了值的情况也会出现文字提示说你没有值 从而校验不通过
      // 算是个歪门邪道吧 但总是解决了问题
      inputSjchange(e) {
        if (this.formData.rule[1].xxx== '' || 0) {
          this.formData.rule[1].xxx= ''
        } else {
          this.formData.rule[1].xxx= Number(this.formData.rule[1].xxx) + 1
          this.formData.rule[1].xxx= Number(this.formData.rule[1].xxx) - 1
        }
      },
      inputSjchange1(e) {
        if (this.formData.rule[1].xxx1== '' || 0) {
          this.formData.rule[1].xxx1= ''
        } else {
          this.formData.rule[1].xxx1= Number(this.formData.rule[1].xxx1) + 1
          this.formData.rule[1].xxx1= Number(this.formData.rule[1].xxx1) - 1
        }
      },


      // 获取编辑时所有数据
      getTransportList() {
        let params= {
          id: this.id
        }
        this.$api.getdetail(params).then(res => {
          if (res.code == 200) {
            this.formData= res.data;
              let validate = this.rules['xxx1'] // 还是取之前的data中定义好的校验规则 
              this.formData.xxx[0].forEach((items, index) => {
                this.rules['xxx' + index] = validate 
              })
           }
        })
      },
      // 提交动态表单
      submit(ref) {
        let query = {
        ... 
        };
        this.$refs.form.validate(this.formData).then(res => {
          if (this.id== null || this.id== '') {
            that.showLoading('加载中', true)
            that.$api.addDtform(query).then(res => {
              if (res.code == 200) {
                that.showMsg('添加成功!')
                that.hideLoading();
              } else {
                that.showMsg(res.msg)
                that.hideLoading()
              }
            })
          } else {
            query.id = that.id;
            that.$api.addDtform(query).then(res => {
              that.showLoading('加载中', true)
              if (res.code == 200) {
                that.showMsg('修改成功!')
                that.hideLoading();
              } else {
                that.showMsg(res.msg)
                that.hideLoading()
              }
            })
          }
        })
      },
      //添加
      add() {
        let item = {
         'XXX':'',
         'XXX1':''
        };
        this.formData.XXX[0].push(item)
        let validate = that.rules['xxx1'] // 还是取之前的data中定义好的校验规则
        this.formDate.xxx[0].forEach((items, index) => {
                this.rules['xxx' + index] = validate 
              })
      
        this.$forceUpdate(this.rules)
      }
    }
  }
</script>

总结:

  1. 代码中我用的是for in 去循环数组的 因为我之前写的动态表单是个对象 前面的索引是从1开始 页面用v-for循环也是从索引 1 开始循环的 介意的话可以全使用foreach 其他 但是用for in 去循环数组也没啥问题 我只是懒得改了;
  2. 主要的bug就是uniapp这些表单不会自动校验 或者说是不会校验第二次就很恶心,所以我在输入框绑定的两个input和blur事件来处理 算是歪门邪道 但也是解决bug的关键方法 ;
  3. 其实在h5中都是可以使用自定义校验表单的格式的 但是微信小程序端不会识别 uniapp官方文档好像有说过 具体用啥正则可以自行去看 我这边就直接绑定blur去判断格式的
  4. 在h5中我们甚至可以在uni-forms-item标签中绑定 rule ,但是在微信小程序中直接报错 所以如果只有h5端 这种方法还简单一点 有微信小程序端的话 添加 编辑时都要动态增加校验规则
   <uni-forms-item label="文字文字" required type="number" :name="'xxx'+index">
          <uni-easyinput  @input="inputSjchange" 
          :inputBorder="false"
          // validatexxxfun 这是在data中定义的自定义校验数据格式的函数
          :rule = "[{required: true,errorMessage: '请输入xxx'},{validateFunction: validatexxxfun}]" 
           v-model="formData.rule[index]['xxx']" placeholder="请输入xxx" />
    </uni-forms-item>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值