Ant Design FormModel 表单校验 - zptime/blog GitHub Wiki

表单和表单检验是很常用的功能,对于一些常用的校验进行了汇总,如默认校验、自定义校验、列表项校验等。特别是列表项的校验,需要特殊关注下:prop="cardList.${index}.idType":rules="rules.idType"

官网 FormModel 表单:https://antdv.com/components/form-model-cn/

基础使用

如下所示,是一个基础的表单信息,其中通过 model 传递表单对象,通过 rules 提供给表单验证规则,并将 FormItemprop 属性设置为需校验的字段名即可。

<template>
  <a-form-model
    class="m-form"
    ref="ruleForm"
    :model="form"
    :rules="rules"
    :label-col="{ span: 4 }"
    :wrapper-col="{ span: 14 }"
  >
    <a-form-model-item label="姓名" prop="name">
      <a-input v-model="form.name" />
    </a-form-model-item>
    <a-form-model-item label="性别" prop="sex">
      <a-radio-group v-model="form.sex">
        <a-radio value="1"></a-radio>
        <a-radio value="2"></a-radio>
      </a-radio-group>
    </a-form-model-item>
    <a-form-model-item label="手机号" prop="mobile">
      <a-input v-model="form.mobile" ref="mobile" placeholder="请输入手机号" />
    </a-form-model-item>
    <a-form-model-item label="证件" prop="cardList">
      <div v-for="card in form.cardList" :key="card.id" class="card-list">
        <a-select v-model="card.idType" placeholder="请选择证件类型">
          <a-select-option :value="1">身份证</a-select-option>
          <a-select-option :value="2">护照</a-select-option>
        </a-select>
        <a-input v-model="card.idNo" placeholder="员工证件号码" />
      </div>
    </a-form-model-item>
    <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
      <a-button type="primary" @click="onSubmit">提交</a-button>
    </a-form-model-item>
  </a-form-model>
</template>

<script>
  import * as R from "ramda";

  export default {
    data() {
      return {
        form: {
          name: "",
          sex: "",
          mobile: "",
          cardList: [
            { id: 1, idType: 1, idName: "身份证", idNo: "111111" },
            { id: 2, idType: 2, idName: "护照", idNo: "sd1234" },
            { id: 3, idType: undefined, idName: "", idNo: "" },
            { id: 4, idType: undefined, idName: "", idNo: "" },
          ],
        },
        rules: {},
      };
    },
    methods: {
      onSubmit() {
        this.$refs.ruleForm.validate((valid) => {
          if (valid) {
            alert("校验成功");
          } else {
            alert("校验失败");
            return false;
          }
        });
      },
    },
  };
</script>

<style lang="scss">
  .m-form {
    .ant-form-item-label {
      line-height: 32px;
    }
    .card-list {
      display: flex;
      align-items: center;
      margin-bottom: 24px;
      .ant-select {
        width: 218px;
        margin-right: 16px;
      }
    }
  }
</style>

默认校验

Form组件提供了基础的表单验证功能,对应大部分情况都是可以处理的。具体的配置项可查看官网,如下只列举了一些基本的配置requiredmessagetrigger

<script>
  export default {
    data() {
      return {
        rules: {
          name: [
            {
              required: true, // 是否必选
              message: "请输入用户姓名", // 校验文案
              trigger: ["change", "blur"], // 触发时机,可以为数组,也可为字符串
            },
            {
              min: 3, // 最小长度
              max: 5, // 最大长度
              message: "姓名长度应该在3~5之间,才符合要求",
              trigger: "blur",
            },
          ],
          sex: [
            {
              required: true,
              message: "请选择性别",
              trigger: "change",
            },
          ],
        },
      };
    },
  };
</script>

自定义校验

对于一些特殊的情况,也可以通过自定义函数validator来校验。如下,以手机号和证件信息为例进行校验,其中手机号validateMobile不仅校验了必填,还校验了格式,而且报错后还可以定位到具体位置focus(),方便修改。

<script>
  export default {
    data() {
      // 手机号验证
      let validateMobile = (rule, value, callback) => {
        if (R.isNil(value) || R.isEmpty(value)) {
          // 定位到错误数据框
          this.$refs.mobile.focus();
          return callback(new Error("请输入手机号"));
        }
        // 格式校验
        let reg = /^1[0-9]\d{9}$/;
        if (!reg.test(value)) {
          this.$refs.mobile.focus();
          return callback(new Error("请输入格式正确的手机号"));
        }
      };

      // 证件校验
      let validateCard = (rule, list, callback) => {
        let flag = false;
        if (!(list && list.length)) {
          flag = true;
        } else {
          R.forEach((o) => {
            if (!o.idType || !o.idNo) flag = true;
          }, list);
        }

        if (flag) {
          callback(new Error("请填写证件信息"));
        }
      };

      return {
        rules: {
          mobile: [
            { required: true, validator: validateMobile, trigger: "change" },
          ],
          cardList: [
            { required: true, validator: validateCard, trigger: "change" },
          ],
        },
      };
    },
  };
</script>

整体检验效果如下图所示,错误信息会展示在对应的表单下方:

图示展示

列表项校验

上面对于证件信息的校验是整体校验,只要有一个不满足条件,整个列表项都会标红,这样体验感就比较差了。正常还是倾向于哪个没填标注哪个,所以还是要对列表的每一项进行单独校验

最关键的配置就是:prop="cardList.${index}.idType",可以配置成.连接的字符串形式,专门处理数组或对象形式的数据。而且要和校验规则:rules="rules.idType"对应起来,不然不会起作用的。

<template>
  <div
    v-for="(card, index) in form.cardList"
    :key="card.id"
    class="card-list card-list2"
  >
    <a-form-model-item
      :label="`证件${index + 1}`"
      :prop="`cardList.${index}.idType`"
      :rules="rules.idType"
    >
      <a-select v-model="card.idType" placeholder="请选择证件类型">
        <a-select-option :value="1">身份证</a-select-option>
        <a-select-option :value="2">护照</a-select-option>
      </a-select>
    </a-form-model-item>
    <a-form-model-item
      :prop="`cardList.${index}.idNo`"
      :rules="rules.idNo"
    >
      <a-input v-model="card.idNo" placeholder="员工证件号码" />
    </a-form-model-item>
  </div>
</template>

<script>
export default {
  data() {
    return {
      rules: {
        idType: [
          {
            required: true,
            message: "请选择证件类型",
            trigger: "change",
          },
        ],
        idNo: [
          {
            required: true,
            message: "请填写证件号码",
            trigger: "change",
          },
        ],
      },
    };
  }
}

图示展示

⚠️ **GitHub.com Fallback** ⚠️