async-validator表单验证

背景:elementui的el-form已经帮我们封装了常用的表单校验,那他是怎么去校验的呢?看文档发现它是利用了async-validator这个插件去实现的(带着好奇心去学习===知其然更要知其所以然)

另一场景需求实现:当我的项目开发有一些表单项 那我们想要实现校验 是不是一定要依赖于el-form呢?当然不是啦
我们一样可以封装类似el-form的属于自己的组件 通过插件async-validator去实现校验

async-validato的使用:https://zhuanlan.zhihu.com/p/269624748

注意:我们进行校验往往更多是针对多个同时进行的 所以async-validato是异步校验 用到了new Promise(解决异步回调)

el-input校验 封装

<template>
  <div class="com-number-input">
    <el-input
      @blur="onValidate"
      @input="onValidate"
      v-model="fieldValue"
      :placeholder="placeholder"
      :clearable="clearable"
    >
      <template #prepend v-if="'prepend' in slots"><slot name="prepend"></slot></template>
      <template #append v-if="'append' in slots"><slot name="append"></slot></template>
    </el-input>
    <div class="error" v-if="errorMessage">{{ errorMessage }}</div>
  </div>
</template>
<script lang="ts" setup name="ComNumberInput">
  import { ref, useSlots } from 'vue'
  import Schema from 'async-validator'

  type Props = {
    modelValue?: string | number
    rules?: Record<string, any>[]
    placeholder?: string
    clearable?: boolean
    validate?: boolean
  }
  const props = withDefaults(defineProps<Props>(), {
    modelValue: '',
    rules() {
      return [] as Record<string, any>[]
    },
    placeholder: '请填写',
    clearable: false,
    validate: true,
  })
  const slots = useSlots()
  const emits = defineEmits(['update:modelValue', 'update:validate'])

  const fieldValue = ref<string | number>('')
  const errorMessage = ref<string>('')
  const validator = new Schema({
    fieldValue: props.rules,
  })
  const onValidate = () => {
    return new Promise((resolve, reject) => {
      validator
        .validate({ fieldValue: fieldValue.value })
        .then(() => {
          errorMessage.value = ''
          emits('update:modelValue', fieldValue.value)
          emits('update:validate', true)
          resolve(true)
        })
        .catch(({ errors, fields }) => {
          if (errors.length > 0) {
            errorMessage.value = errors[0].message
            emits('update:validate', false)
          }
          reject(errors)
        })
    })
  }
  watch(
    () => props.modelValue,
    (newVal) => {
      fieldValue.value = newVal
    },
  )
  onMounted(() => {
    fieldValue.value = props.modelValue
  })
  defineExpose({
    validate() {
      return new Promise((resolve, reject) => {
        onValidate()
          .then(() => {
            if (errorMessage.value == '') {
              resolve(true)
            } else {
              resolve(false)
            }
          })
          .catch(() => {
            resolve(false)
          })
      })
    },
  })
</script>
<style lang="scss" scoped>
  .com-number-input {
    .error {
      text-align: left;
      color: var(--el-color-danger);
    }
  }
</style>

调用:

<com-number-input
                  ref="beginFinalScoreRef"
                  v-model="paramsForm.beginFinalScore"
                  class="flex-1"
                  clearable
                  :rules="[
                    {
                      validator(field, value) {
                        return !isNaN(value)
                      },
                      message: '请输入数字',
                    },
                    {
                      validator(field, value) {
                        return value >= 0
                      },
                      message: '不能为负数',
                    },
                  ]"
                  placeholder="数字"
                ></com-number-input>

const onQuery = async () => {
    if (
      !((await beginFinalScoreRef.value.validate()) && (await endFinalScoreRef.value.validate()))
    ) {
      return
    }

}

你可能感兴趣的:(vue.js,前端,javascript)