我常用的vue移动端form表单验证方法

550 阅读1分钟

介绍

开发移动端的项目(pc的项目我基本都直接用UI框架的了。。)常会遇到提交表单前,验证表单的需求,如果使用了第三方的UI库这个很好实现,第三方库基本都提供了form验证的api,比如

<el-form
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm"
    :size="formSize"
    status-icon
  >
    <el-form-item label="Activity name" prop="name">
      <el-input v-model="ruleForm.name" />
    </el-form-item>
...
<van-form @failed="onFailed"> 
    <van-cell-group inset> 
        <!-- 通过 pattern 进行正则校验 --> 
        <van-field 
            v-model="value1" 
            name="pattern" 
            placeholder="正则校验" 
            :rules="[{ pattern, message: '请输入正确内容' }]" 
        />
....

但有时移动端的表单并不那么复杂,而且需要按照公司的设计稿绘制,于是我就写了一个简单的验证表单的方法:

validForm.js
目前支持 required、pattern,你可以在代码里添加校验规则

import { showToast } from './toast'

/**
 *
 * @param {object} formObj
 * @param {Array<any>} rulesArr
 * @returns
 */
export default function validForm(formObj = {}, rulesArr = []) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < rulesArr.length; i++) {
      const keyObj = rulesArr[i]
      for (let key in keyObj) {
        const keyRules = keyObj[key]
        for (let k = 0; k < keyRules.length; k++) {
          const keyRule = keyRules[k]
          /**
           * 这里开始验证
           */
          // 必填
          if (keyRule.required) {
            let isRequired
            if (typeof keyRule.required == 'function') {
              isRequired = keyRule.required()
            } else {
              isRequired = true
            }
            if (isRequired) {
              if (!formObj[key]) {
                showToast.warning(keyRule.message ?? '请输入' + key)
                return reject()
              }
            }
          }
          // 正则
          if (keyRule.pattern) {
            if (!keyRule.pattern.test(formObj[key])) {
              showToast.warning(keyRule.message ?? '请输入正确格式的' + key)
              return reject()
            }
          }
          /// 这里你可以添加新的规则
        }
      }
    }

    return resolve()
  })
}
参数类型说明
参数1 formObjobjectform的对象
参数2 rulesArrRule[]规则数组

Rule

字段类型说明
required( boolean | () => boolean )是否必填
patternRegExp正则表达式
messagestring规则不符合时的提示语

使用

需要设置formformRules两个变量,<tempalte>中只要 v-model 双向绑定就行,然后提交的时候,调用validForm(form, formRules)

    // template中 只需要 v-model 双向绑定就行
    <view class="form">
      <view class="form_item"><input placeholder="请输入手机号码" v-model="formModel.form.phoneNumber" /></view>
      <view class="form_item">
        <input placeholder="请输入验证码" v-model="formModel.form.sms" />
      </view>
    </view>
    
    ...

    const formModel = reactive({
      form: {
        phoneNumber: '',
        sms: '',
      },
    })
    const formRules = [
      {
        phoneNumber: [
          { required: true, message: '请输入手机号码' },
          { pattern: patternCreator.mobilePhone.pattern, message: '请输入正确格式的手机号' },
        ],
      },
      { sms: [{ required: true, message: '请输入验证码' }] },
    ]
    
    ...
    
    // 提交
    async function submit() {
      // 验证
      await validForm(formModel.form, formRules) // 验证
      ...
    }

为什么参数2 rulesArr是一个数组

如果rulesArr是一个对象的话,可以减少一次遍历
但是我希望校验的顺序是按照rulesArr的顺序,即先校验 phoneNumber 然后 sms,如果phoneNumber报错就不往下走了。

而如果写成对象,就得用Object.keys,但是Object.keys并不能保证遍历的顺序。