Vue 验证框架 Vee基本使用与服务端集成

版权声明:欢迎转载,标明出处 https://blog.csdn.net/mz4138/article/details/81911002

验证框架 Vee-validate

官网: https://baianat.github.io/vee-validate/

安装

# install with npm
npm install vee-validate

# install with yarn
yarn add vee-validate

基本使用

main.js 加入 VeeValidate 模块

import Vue from 'vue';
import VeeValidate from 'vee-validate';

Vue.use(VeeValidate);

验证与错误信息

<input type="username" v-validate="{required:true}" class="form-control"  name="username" v-model="username" >
<span class="errorHint">{{errors.first("username")}}</span>

效果: 当节点input[name='username'] 为空时提示"The username field is required."

  1. 根据input标签的name属性绑定,(name属性必须存在)
  2. v-validate 指定验证规则,(v-validate标签必须存在)
  3. errors.first(“username”) 获取name=”username”标签的错误信息显示在界面

验证规则:

key 参数 描述
required true|false 字段是否必须填写
is 目标字段对象 当前字段与目标字段值是否相等
email 邮箱 验证邮箱格式
date_format 日期 验证日期格式
length 字符串 长度必须等于XX
min 字符串 最小长度
max 字符串 最大长度
min_value 数字 最小值
max_value 数字 最大值
regex 正则表达式字符串 当前字段的值是否能通过正则验证

更多验证规则参见官网: https://baianat.github.io/vee-validate/guide/rules.html#after

与服务端的验证信息集成

本节阐述如何在http请求时,对返回的内容进行处理。 属于原理内容

服务端错误

{
  "success": 30,
  "message": "验证信息错误",
  "data": {
    "password": "密码不能为空",
    "username": "用户名不能为空"
  }
}

客户端请求示例:

 httputil.post('/api/login/account',{username:this.username,password:this.password},{validate:{error:this.errors,validator:this.$validator}}).then((res) =>{
         // 客户端对服务端返回对象的<<data对象>>的处理
 })

加入两个参数:{validate:{error:this.errors,validator:this.$validator}}
1. this.errors 用于添加服务端返回的异常
2. this.$validator 用于验证请求字段 以及 找到服务端返回的字段对应本地字段的id

分组验证

客户端请求

// manager 组
<input type="text" class="form-control"  v-validate="{required:'手机'}" data-vv-scope="manager" name="phone"  v-model="changeManager.phone">
<span class="errorHint">{{errors.first("phone","manager")}}</span>

//password组
<input type="password" v-validate="{required:'原密码'}"  data-vv-scope="password"  class="form-control" name="password" v-model="password"/>
<span class="errorHint">{{errors.first("password","password")}}</span>

基本使用的区别如下
1. 通过 data-vv-scope 指定验证分组
2. errors.first(nane字段,分组)

中文错误信息

import cn from 'vee-validate/dist/locale/zh_CN';
import VeeValidate, { Validator } from 'vee-validate';

Validator.localize('cn', cn);

通过 Validator.localize 指定语言会覆盖默认的报错信息

自定义错误信息

在main.js 中 自定义错误信息

// 修改默认错误信息
const dict = {
  cn: {messages: {
      is: (name,param) =>{
        if(param === null || param === undefined || param.length===0){
          throw "验证字段的别名不存在:"+name;
        }
        return param[1];
      }
  }}  // name接受alias的值.
}
Validator.localize(dict);

dict 对象说明:
1. cn 指定语言是中文
2. cn.messages 覆盖消息
3. cn.messages.is 当指定验证规则v-validate="{ is: confirmation }" 时, password和password_confirmation标签的内容不一致时,返回错误is的自定义错误信息

is 标签:

<input v-validate="{ is: [confirmation,'is的自定义错误信息'] }" type="text" name="password">
<input v-model="confirmation" type="text" name="password_confirmation">

错误信息覆盖形式:

例如

Validator.localize('cn', cn);
Validator.localize(dict);
  1. dict 最后指定的优先级最高
  2. cn 第二优先级,覆盖en指定的部分内容.没有全部覆盖
  3. en 默认错误语言

附注

http.js 请求封装

import Vue from 'vue'

import api from '../../config/api'

import router from '../router'
// 中断信号类
class HttpBreakPromise{
  constructor(){}
}

//删除undifined对象
function deleteEmptyProperty(object){
  for (var i in object) {
    var value = object[i];
    if (typeof value === 'object') {
      if (Array.isArray(value)) {
        if (value.length == 0) {
          delete object[i];
          continue;
        }
      }
      deleteEmptyProperty(value);
      if (isEmpty(value)) {
        delete object[i];
      }
    } else {
      if (value === '' || value === null || value === undefined) {
        delete object[i];
      } else {
      }
    }
  }
}
function isEmpty(object) {
  for (let name in object) {
    return false;
  }
  return true;
}

// 客户端本地验证
const validateSimpleFilter = (info)=> {
  if(!info || !info.validate){
    return Promise.resolve();
  }
  let validator = info.validate.validator;
  let errors = info.validate.error;
  let scope = info.validate.scope;

  scope = scope ? scope + ".*" : '*';
  return validator.validate(scope).then((descriptor, value, options) => {
    if (!descriptor) {
      throw "验证错误";
    }
  })
}
// 服务端返回内容验证
const validateFilter = (promise,info)=>{
  if(!info || !info.validate){
    return promise;
  }
    let validator = info.validate.validator;
    let errors = info.validate.error;
    let scope = info.validate.scope;

    scope = scope?scope+".*":'*';
    return validator.validate(scope).then((descriptor, value, options)=>{

      if(!descriptor){

        throw "验证错误";
      }
    }).then(()=>{
       mask(promise,info);
      return promise.then(res=>{
        if(res.success !== 30){
          // 只针对状态码为30的,进行错误值绑定
          return res;
        }
        let resData = res.data;
        errors.clear();

        let fields = validator.fields;
        for(let eIndex in resData){
          let findItem = fields.find({name:eIndex});
          let errorObj = {
            field: eIndex,
            msg: resData[eIndex],
            id: findItem.id
          };

          errors.add(errorObj)
        }
        return res;
      });

    })

}
// 请求处理器
const requestHandler=(promise,info)=>{
  // 添加遮罩
  mask(promise,info);
  //服务端返回验证
  validateFilter(promise,info)
  //登录过滤器
  loginFilter(promise,info);
  // 返回值 处理
  return resultFilter(promise,info);

}


// 遮罩
const mask = (promise,info)=>{
  var index = layer.load(2, {content:'加载中...',success: function(layero){
      layero.find('.layui-layer-content').css({'padding-top':'50px',"text-align":"center","width":"100px","background-position": "34px 12px","background-color": "white","box-shadow": "0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12)","border-radius": "6px","height":"85px"});
    }
  })
    return promise.then(res=>{

      //获得结果后,弹出遮罩
      let toast = info ? info.toast:{};
      let result = res.body;
      if (result.success === 20) {
        if(toast&&toast.success){
          layer.msg(toast.success, {
            icon: 1,
            shade: 0.2,
            scrollbar: false,
            shadeClose:true
          });
        }
      }else{
        if(toast&&toast.fail){
          layer.msg(toast.fail, {
            icon: 2,
            shade: 0.2,
            scrollbar: false,
            shadeClose:true
          });
        }
      }
      //获得结果后,删除遮罩
      layer.closeAll('loading')

    })

}
// 返回值过滤器
const resultFilter = (promise,info) => {
    return promise.then(res => {
      let result = res.body;
      if(result.success!==20){
        throw new HttpBreakPromise();
        // Promise.break;  ES6 原生 不提供 Promise.break; 形式中断promise调用链。
        // 只能抛出异常,在调用者那边处理异常
      }
      if(info && info.allObj){
        return result;
      }
      return result.data
    }).catch((err)=>{
      //加入HTTP调试错误
      console.log("http调试错误:",err);
      return new Promise((resolve, reject)=>{});
    });

}

const loginFilter = (promise,info)=>{
  return promise.then(function(response){
    layer.closeAll('loading')
    let success = response.body.success;
    if(success===900){
      layer.msg("登录已过期", {
        icon: 2,
        shade: 0.2,
        scrollbar: false,
        shadeClose:true,
        time:2000
      })
      router.push('/');
      return response;
    }
    var errorType=info&&info.error;
    if(errorType && success!==20){
      router.push('/error/error');
    }
    return response;
  })
}

const info= {toast :{},allObj:false,page:{}}
const httputil = {
    name:"httputil",
  get(url = {},params = {},info = info) {

    if(info&&info.page){
      params = $.extend({},{currentPage:info.page.currentPage,showCount:info.page.showCount},params);
    }

   // delete info.error
    deleteEmptyProperty(params);
    return validateSimpleFilter(info).then(()=>{
      return requestHandler(Vue.http.get(api.BASE_URL + url,{params:params,withCredentials: true}),
        info);
    });
  },
  post(url = {}, params = {},info= info) {
    return validateSimpleFilter(info).then(()=>{
      return requestHandler(Vue.http.post(api.BASE_URL + url, params,{withCredentials: true})
        ,info);
    })
  },
  put(url = {}, params = {},info= info) {

    return validateSimpleFilter(info).then(()=>{
      return requestHandler(
        Vue.http.put(api.BASE_URL + url, params, {withCredentials: true})
        ,info);
    })
  },
  delete(url = {}, params = {},info= info) {
    return validateSimpleFilter(info).then(()=>{
      return requestHandler(
        Vue.http.delete(api.BASE_URL + url, {body:params},{withCredentials: true})
        ,info);
    })

  },
}

export default httputil;


猜你喜欢

转载自blog.csdn.net/mz4138/article/details/81911002