使用 async-validator 自定义校验规则实现 table 组件的循环表单校验功能

首先我们构建表单的 dom 元素,这里我们使用的是 render 函数代替 template,利用 scopedSlots 字段向子组件中传入一个作用域插槽的对象。

<a-table
  rowKey={(record, index) => index + record.varietyCode}
  pagination={false}
  data-source={this.tableData}
  columns={columns.call(this, h)}
  {...{ scopedSlots: this.scopedSlotsList }}
/>

由于不同的 mode 形式下,可能 column 项是可编辑的,也有可能是不可以编辑,只能查看相关数据的。

const validators = []
scopedSlotsList () {
  const obj = {}
  Array.prototype.forEach.call(['applyAssistQty'], item => {
    obj[item] = (text, record, index) => {
      return (['edit', 'add'].includes(this.mode) || (record.waitInfo === true && this.mode === 'tracking'))
        ? <cell-validate mode="a-input-number"
          validateProp={`${item}${index}`}
          validators={validators}
          rules={[{ required: true, message: '该选项必填' }, {
            validator: (rule, value, callback) => {
              ......
              return callback()
            },
          }]}
          v-model={this.tableData[index][item]} />
        : text
    }
  })
}

我们可以看到上述 cell-validate 组件就是我们要实现的表单校验功能组件。

mode: 标签名或组件名

validateProp:校验组件的 prop 属性,由于是循环表单,我们添加了 index 的值

validators:要校验的组件

rules: 校验规则

同时向外还提供了两个方法:validate 和 clearValidate

validate: 用来校验

clearValidate 用来清空校验规则

async validate () {
  try {
    await Promise.all([...validators.map(vm => vm.validate())])
    return true
  } catch (err) {
    return false
  }
}
async clearAllValidate () {
  await [...validators.map(vm => vm.clearValidate())]
},

接下来就是如何实现 cell-validate 组件?

我们再来回顾下 async-validator 的基本用法:ant-design-vue 表单验证和 validator 自定义表单验证

validate 校验表单方法就是采用 async-validator 的基本用法实现的,使用 errorMessage 记录错误信息,清空校验只需将errorMessage 清空即可。

validate () {
  // 真正校验的的时候再生成validator函数
  if (!this.validateProp || !this.rules) return Promise.resolve(true)
  const descriptor = {
    [this.validateProp]: this.rules,
  }
  const validator = new Schema(descriptor)
  if (!validator) return Promise.resolve(true)
  const model = {
    [this.validateProp]: this.$attrs.value,
  }
  return validator.validate(model, (errors, fields) => {
    this.errorMessage = errors ? errors[0].message : ''
  })
},
clearValidate () {
  this.errorMessage = ''
},

我们可以看到我们使用的 validators 是由验证表单内部创建的。

created () {
  this.validators.push(this)
},
beforeDestroy () {
  const index = this.validators.findIndex(vm => vm._uid === this._uid)
  if (index >= 0) {
    this.validators.splice(index, 1)
  }
},

由于传入的自己自身有一些 attribute 和 事件,在添加校验规则的同时如何拥有组件自身的属性呢?我们将使用 $attrs  和 $listeners 来获取。详情请查看:在 render 函数中,Vue 实例属性:$attrs、$props、$listeners 和 $scopedSlots的使用

render (h) {
  return <div class={this.errorMessage ? 'has-error' : ''} style="position:relative;">
    {
      h(this.mode,
        {
          style: {
            width: '100%',
          },
          props: {
            ...this.$attrs,
            dropdownMatchSelectWidth: false,
          },
          on: {
            ...this.$listeners,
            select: (param) => this.$emit('select', param),
            change: this.handleChange,
          },
        }
      )
    }
    { this.errorMessage && <span style="color:red;font-size:12px;line-height:1;">{this.errorMessage}</span> }
  </div>
},

进阶版:

如何给选中的 table 行添加校验规则,未选中的行则取消校验规则呢?

由于校验规则是通过组件外部传入的,所以在添加出做校验规则那里只需做判断处理即可。

scopedSlotsList () {
  const obj = {}
  Array.prototype.forEach.call(['weight'], item => {
    obj[item] = (text, record, index) => {
      return <cell-validate mode="a-input-number" class="w140"
        validateProp={`${item}${index}`}
        validators={validators}
        rules={this.asyncRules(record, item)}
        v-model={this.tableData[index][item]} />
    }
  })
  return obj
},

我们可以上述的校验规则是由 asyncRules 所产生的。这里的 asyncRules 可以使用计算属性也可以使用方法实现。对于勾选的数据则返回校验规则即可,未勾选的返回 null。

asyncRules () {
  return function (record, key) {
    if (this.selectedRowKeys.includes(record.id) && ['weight'].includes(key)) {
      return {
        validator: (rule, value, callback) => {
          ......
          return callback()
        },
      }
    }
    return
  }  
},

// 组件 validate 校验方法
validate () {
  // 真正校验的的时候再生成validator函数
  if (!this.validateProp || !this.rules) return Promise.resolve(true)
  ......
},

 

async-validator是基于Node.js和浏览器的表单验证库,它支持同步和异步验证规则。在async-validator中,你可以自定义校验规则来满足特定的验证需求,尤其是在进行异步校验时非常有用。 自定义校验通常需要提供一个校验函数,该函数接受当前字段的值和一个回调函数作为参数。校验函数的职责是根据提供的值进行校验,并在完成校验后通过回调函数返回校验结果。回调函数需要传递一个错误对象,如果校验未通过,则需要提供错误信息。 下面是一个简单的自定义校验规则的例子: ```javascript import { createForm } from 'async-validator'; const descriptor = { name: { type: 'string', required: true, asyncValidator: (rule, value, callback) => { setTimeout(() => { // 模拟异步操作 if (!value.includes('hello')) { callback(new Error('必须包含关键字"hello"')); } else { callback(); } }, 1000); }, }, }; const validator = createForm(descriptor); validator.validate({ name: 'hi' }, errors => { console.log(errors); // 输出校验错误信息 }); ``` 在这个例子中,我们定义了一个名为`name`的字段,它必须是字符串类型,并且是必填的。我们还定义了一个`asyncValidator`规则,它是一个异步校验函数。在这个函数中,我们使用`setTimeout`模拟了一个异步操作,如果字段值`value`不包含关键字`"hello"`,则会调用回调函数`callback`并传递一个错误对象,否则传递`null`表示校验通过。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值