vue项目中使用vee-validate表单验证

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue项目中使用vee-validate表单验证相关的知识,希望对你有一定的参考价值。

官方文档 https://vee-validate.logaretm.com/v4/  支持vue3.0

npm https://www.npmjs.com/package/vee-validate

1.安装包

npm i vee-validate@4.0.3

 2. 引入 组件 

import { Form, Field } from 'vee-validate'

components:{Form, Field}

3.结构

form就是表单 field就是表单项 ===input

<Form>
      <Field v-model="formData.mobile" name="mobile" type="text" placeholder="请输入手机号" />
      <Field v-model="formData.password" name="password" type="password" placeholder="请输入密码" />
</Form>

4.定义校验规则 

整体用一个对象包起来,每条规则就是一个函数。具体格式如下:

  • 参数1:是要验证的值,参数2:是验证对象{field, form}

  • 返回值:true表示通过验证,返回字符串表示校验错误。

    // 定义校验规则
    const schema = {
      account  (value) {
        if (!value) {
          return '用户名不能为空,请检查!'
        }
        return true
      },
      mobile (value) {
        if (!value) return '请输入手机号'
        if (!/^1[3-9]\\d{9}$/.test(value)) return '手机号格式错误'
        return true
      },
      password (value) {
        if (!value) return '请输入密码'
        if (!/\\d{6}$/.test(value)) return '密码格式错误'
        return true
      },
      isAgree (value) {
        return value || '不答应可不行'
      }
    }

5.使用规则

form:
ref: 引用;后边手动兜底校验要使用
validation-schema: 用来指定校验规则(这里的规则) 
v-slot: 作用域插槽,如果校验失败,errors中会保存校验失败的结果

 Field:

v-model:双向绑定数据项
name:指定要校验的字段
:class="{error:errors.mobile}" 如果校验失败,就补充error类
动态绑定class用来约定错误发生时的样子

<Form ref="target" :validation-schema="schema" v-slot="{errors}">
  		<!-- 省略其他 ... -->
      <Field 
             v-model="formData.mobile" 
             type="text" 
             name="mobile"
             placeholder="请输入手机号" 
             :class="{error:errors.mobile}"
       />
  		<!-- 约定显示校验错误结果 -->
       <div class="error" v-if="errors.mobile">{{errors.mobile}}</div>
  
       <!-- 省略其他 ... -->
</Form>

 6.手动兜底校验

    const login = () => {
      target.value.validate().then((res) => {
        console.log('表单校验结果', res)
      })
    }

7.总体代码

1.    用Form去替换原来的form, 用Field去替换原input元素
            1.    Form中要使用:ref, validation-schema, v-slot
            2.    Field中设置v-model, name, class
2.     补充dom结构来存放校验错误提示(在element, vant等组件库中,我们是不需要写的)
3.    用`as` 来特殊处理xtxCheckBox组件

<template>
  <div class="account-box">
    <!-- 登录方式切换 -->
    <div class="toggle">
      <a
        href="javascript:;"
        v-if="isMsgLogin"
        @click="isMsgLogin = !isMsgLogin"
      >
        <i class="iconfont icon-user"></i> 使用账号登录
      </a>
      <a href="javascript:;" v-else @click="isMsgLogin = !isMsgLogin">
        <i class="iconfont icon-msg"></i> 使用短信登录
      </a>
    </div>
    <!--
      ref: 引用;后边手动兜底校验要使用
      validation-schema: 用来指定校验规则(这里的规则)
      v-slot: 作用域插槽,如果校验失败,errors中会保存校验失败的结果
    -->
    <Form
      class="form"
      ref="target"
      :validation-schema="schema"
      v-slot="{ errors }"
    >
      <!-- 使用账号登录 -->
      <template v-if="!isMsgLogin">
        <div class="form-item">
          <div class="input">
            <i class="iconfont icon-user"></i>
            <!--
              Field: v-model:双向绑定数据项
                    name:指定要校验的字段
                    :class="{error:errors.mobile}" 如果校验失败,就补充error类
              动态绑定class用来约定错误发生时的样子 -->
            <!-- <input type="text" placeholder="请输入用户名" /> -->
            <Field
              v-model="form.account"
              name="account"
              type="text"
              placeholder="请输入用户名"
              :class="{error:errors.account}"
            ></Field>
          </div>
           <div class="error" v-if="errors.account">{{errors.account}}</div>
          <!-- <div class="error"><i class="iconfont icon-warning" />请输入手机号</div> -->
        </div>
        <div class="form-item">
          <div class="input">
            <i class="iconfont icon-lock"></i>
             <Field
              v-model="form.password"
              name="password"
              type="text"
              placeholder="请输入密码 长度为6位"
              :class="{error:errors.password}"
            ></Field>
            <!-- <input type="password" placeholder="请输入密码" /> -->
          </div>
           <div class="error" v-if="errors.password">{{errors.password}}</div>
        </div>
      </template>

      <!-- 使用验证码登录 -->
      <template v-else>
        <div class="form-item">
          <div class="input">
            <i class="iconfont icon-user"></i>
            <!-- <input type="text" placeholder="请输入手机号" /> -->
             <Field
              v-model="form.mobile"
              name="mobile"
              type="text"
              placeholder="请输入用户名"
              :class="{error:errors.mobile}"
            ></Field>
          </div>
          <div class="error" v-if="errors.mobile">{{errors.mobile}}</div>
        </div>
        <div class="form-item">
          <div class="input">
            <i class="iconfont icon-code"></i>
            <input type="password" placeholder="请输入验证码" />
            <span class="code">发送验证码</span>
          </div>
        </div>
      </template>

      <div class="form-item">
        <div class="agree">
          <Field as="XtxCheckbox" name="isAgree" v-model="form.isAgree" />
            <span>我已同意</span>
            <a href="javascript:;">《隐私条款》</a>
            <span>和</span>
            <a href="javascript:;">《服务条款》</a>
        </div>
           <div class="error" v-if="errors.isAgree"><i class="iconfont icon-warning" />{{errors.isAgree}}</div>
      </div>
      <a href="javascript:;" @click="login" class="btn">登录</a>
    </Form>
    <div class="action">
      <!-- qq登录 -->
      <img
        src="https://qzonestyle.gtimg.cn/qzone/vas/opensns/res/img/Connect_logo_7.png"
        alt=""
      />
      <div class="url">
        <a href="javascript:;">忘记密码</a>
        <a href="javascript:;">免费注册</a>
      </div>
    </div>
  </div>
</template>
<script>
import { ref, reactive } from 'vue'
import { Form, Field } from 'vee-validate'
export default {
  components: { Form, Field },
  setup () {
    //   是否短信登录
    const isMsgLogin = ref(false)
    // 定义校验规则
    const schema = {
      account  (value) {
        if (!value) {
          return '用户名不能为空,请检查!'
        }
        return true
      },
      mobile (value) {
        if (!value) return '请输入手机号'
        if (!/^1[3-9]\\d{9}$/.test(value)) return '手机号格式错误'
        return true
      },
      password (value) {
        if (!value) return '请输入密码'
        if (!/\\d{6}$/.test(value)) return '密码格式错误'
        return true
      },
      isAgree (value) {
        return value || '不答应可不行'
      }
    }

    const target = ref(null)

    // 表单对象数据
    const form = reactive({
      isAgree: false,
      account: null,
      password: null,
      mobile: null,
      code: null
    })
    // 登陆时自定义校验
    const login = () => {
      target.value.validate().then((res) => {
        console.log('表单校验结果', res)
      })
    }
    return { isMsgLogin, schema, target, form, login }
  }
}
</script>
<style lang="less" scoped>
// 账号容器
.account-box {
  .toggle {
    padding: 15px 40px;
    text-align: right;
    a {
      color: @xtxColor;
      i {
        font-size: 14px;
      }
    }
  }
  .form {
    padding: 0 40px;
    &-item {
      margin-bottom: 28px;
      .input {
        position: relative;
        height: 36px;
        > i {
          width: 34px;
          height: 34px;
          background: #cfcdcd;
          color: #fff;
          position: absolute;
          left: 1px;
          top: 1px;
          text-align: center;
          line-height: 34px;
          font-size: 18px;
        }
        input {
          padding-left: 44px;
          border: 1px solid #cfcdcd;
          height: 36px;
          line-height: 36px;
          width: 100%;
          &.error {
            border-color: @priceColor;
          }
          &.active,
          &:focus {
            border-color: @xtxColor;
          }
        }
        .code {
          position: absolute;
          right: 1px;
          top: 1px;
          text-align: center;
          line-height: 34px;
          font-size: 14px;
          background: #f5f5f5;
          color: #666;
          width: 90px;
          height: 34px;
          cursor: pointer;
        }
      }
      > .error {
        position: absolute;
        font-size: 12px;
        line-height: 28px;
        color: @priceColor;
        i {
          font-size: 14px;
          margin-right: 2px;
        }
      }
    }
    .agree {
      a {
        color: #069;
      }
    }
    .btn {
      display: block;
      width: 100%;
      height: 40px;
      color: #fff;
      text-align: center;
      line-height: 40px;
      background: @xtxColor;
      &.disabled {
        background: #cfcdcd;
      }
    }
  }
  .action {
    padding: 20px 40px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .url {
      a {
        color: #999;
        margin-left: 10px;
      }
    }
  }
}
</style>

8.校验复用 

如果还有其它校验和上面的一样 我们可以采用抽里成一个js文件进行复用

validate.js

export const account = (value) => {
  if (!value) {
    return '用户名不能为空,请检查!'
  }
  return true
}
export const mobile = (value) => {
  if (!value) return '请输入手机号'
  if (!/^1[3-9]\\d{9}$/.test(value)) return '手机号格式错误'
  return true
}
export const password = (value) => {
  if (!value) return '请输入密码'
  if (!/\\d{6}$/.test(value)) return '密码格式错误'
  return true
}
export const isAgree = (value) => {
  return value || '不答应可不行'
}

引入校验

import { account, isAgree, password, mobile } from '@/utils/validate'

setup(){
    const schema = {
      account, mobile, password, isAgree
    }
}

以上是关于vue项目中使用vee-validate表单验证的主要内容,如果未能解决你的问题,请参考以下文章

vue表单验证,vee-Validate

vue2移动端使用vee-validate进行表单验证

Vue 表单校验 vee-validate

关于 vee-validate直接引用的方法

使用 Vee-Validate 和 vue js 2 在提交时验证子输入组件

使用vee-validate表单插件是如何设置中文提示?