2021-07-09

Vue Element-ui表单校验规则,你掌握了哪些?

- 如何判断属性值是否在某个范围内,且这个范围可以任意指定?- 如何判断属性值是否为某个值?- 多个属性联合校验,当前属性的校验规则依赖于另一个属性的值,如何进行校验?- 两种模式,进入同一个表单组件,某些栏位可以不使用校验规则,即rules的对象会有所不同。这种情况如何处理?有必要深入了解Vue element-ui的表单校验规则。

1、前言

  Element-ui表单校验规则,使得错误提示可以直接在form-item下面显示,无需弹出框,因此还是很好用的。

  我在做了登录页面的表单校验后,一度以为我已经很了解表单的校验规则。但我在深入使用表单校验规则时,遇到下列问题:

  • 如何判断属性值是否在某个范围内,且这个范围可以任意指定?
  • 如何判断属性值是否为某个值?
  • 多个属性联合校验,当前属性的校验规则依赖于另一个属性的值,如何进行校验?如注册页面,ID类型有邮箱地址、手机号和身份证号码,选择不同类型,IDValue属性的校验规则是不同,如何处理?
  • 两种模式,进入同一个表单组件,某些栏位可以不使用校验规则,即rules的对象会有所不同。这种情况如何处理?

  上述问题,让我感觉几乎成了小白。于是迫使我从头开始研究校验规则,查阅相关文档。

  本文分享一下对于表单校验规则的心得体会。

2、规则校验的入门模式

2.1、示例代码

  作为规则校验的入门,以登录页面为例,代码如下:

<template> <div >  <el-form ref="form" :model="form" :rules="rules" label-width="80px" >  <h2 >XX管理系统登录</h2>  <el-form-item label="用户名:" prop="username">  <el-input v-model="form.username"></el-input>  </el-form-item>  <el-form-item label="密 码:" prop="password">  <el-input v-model="form.password" type="password"></el-input>  </el-form-item>  <el-form-item label="验证码:" prop="verifyCode">  <el-input v-model="form.verifyCode"></el-input>  <div @click="getVerifyCode(true)">   <img id="verifyCodeImg" alt="点击更换" title="点击更换" />  </div>  </el-form-item>  <el-form-item>  <el-button type="primary" id="login" @click="submitForm('form')">登录</el-button>  </el-form-item> </el-form> </div> </template><script>import { mapMutations } from 'vuex'export default { data() { return {  form: {  username: "",  password: "",  verifyCode: "",  },  rules: {  username: [   {required: true, message: "用户名不能为空", trigger: 'blur'},  ],  password: [   {required: true, message: "密码不能为空", trigger: 'blur'},   {min: 6, max: 30, message: "密码6-30位", trigger: 'blur'}  ],  verifyCode: [   {required: true, message: "验证码不能为空", trigger: 'blur'},  ]  }   };  }, methods: { // 提交登录 submitForm(formName) {  let _this = this;   // 执行校验  this.$refs[formName].validate(valid => {  // 验证通过为true,有一个不通过就是false  if (valid) {   // 通过校验   // 登录处理   // ....  } else {   // 没通过校验   console.log('验证失败');   return false;  }  }); }, } }</script>

2.2、form项

  form项,指明使用校验规则:

 <el-form ref="form" :model="form" :rules="rules" label-width="80px" >

  :rules="rules" 指明了校验规则使用rules规则对象,你也可以使用其它名称,如rules1。

2.3、prop项

  prop项,指明哪些字段可能使用校验规则:

  <el-form-item label="用户名:" prop="username">  <el-input v-model="form.username"></el-input>  </el-form-item>

  如果prop项指定的属性值,如username,在rules中也有相应的项,则表示该属性值执行规则校验。这个属性必须是form的model属性绑定的数据对象的属性,本例中为form,其在data中定义:

  form: {  username: "",  password: "",  verifyCode: "",  },

2.4、rules项

  rules项,即校验规则集,其在data中定义,其名称必须与form的:rules属性绑定的rules规则对象名一致。

  rules: {  username: [   {required: true, message: "用户名不能为空", trigger: 'blur'},  ],  password: [   {required: true, message: "密码不能为空", trigger: 'blur'},   {min: 6, max: 30, message: "密码6-30位", trigger: 'blur'}  ],  verifyCode: [   {required: true, message: "验证码不能为空", trigger: 'blur'},  ]  }  

  这是一个对象,每个元素的类型为:{属性名:[rule]},属性名对于prop的属性值。[rule]是一个规则数组,规则数组的每一项是一条对本属性的校验规则。

2.5、rule项

  rule项,即规则数组的元素,这是本文要重点探讨的项目。这里先就上述rules的各元素项解析一下:

  • required:表示是否必须有值,取值为true/false,如为true,表示必须有值,如果无值,则校验不通过;如为false,则允许无值,但在有值的情况下,不影响其它规则的使用。
  • message:提示消息,在校验不通过时提示此消息。
  • trigger:触发方式,取值为blur/change,blue表示失去焦点,一般在input组件中使用;change为值改变,一般在选择框中使用。
  • min:字符串最小长度。
  • max:字符串最大长度。

  有了这些解释,不难理解上述rules定义的各属性的校验规则。

2.6、使用规则

this.$refs['form'].validate(valid => {  // 验证通过为true,有一个不通过就是false  if (valid) {   // 通过校验  } else {   // 没通过校验  }  });

  这个validate方法,要求所有校验规则都通过,才放行。其中,$refs['form'],指向form的ref属性值。

2.7、规则校验的核心

  规则校验的核心为为async-validator插件,官网:https://github.com/yiminghe/async-validator。

  Element-UI使用了该插件,并进行了封装。官网:https://element.eleme.cn/#/zh-CN/component/form。

  因此两边的资料都会有帮助。

3、规则校验的进阶模式

3.1、嵌套对象属性名

  有时候,prop不是一个简单的属性,而是包在其它对象下的属性。如:

  <el-form-item label="登 录 名:" prop="formData.loginName">  <el-input v-model="form.formData.loginName" :disabled="form.formData.userId != 0"></el-input>  </el-form-item>

  form的model绑定的form对象,其形式为:

  form:{   // form数据字段,为提交后端方便,建议与UserInfo字段命名一致   formData : {   userId  : 0,   loginName : '',   passwd  : '',   // ...   },   // 用户类型选择框当前显示值   userTypeLabel : "",   // ...  },

  此时,rules的元素定义,不能用下列形式:

  formData.loginName: [   {required: true, message: "登录名不能为空", trigger: 'blur'},  ],

  这样,编译会报错!

  应使用下列形式:

 'formData.loginName': [  {required: true, message: "登录名不能为空", trigger: 'blur'}, ],

  即用单引号或双引号将之包起来,变成一个字符串。

3.2、自定义校验器validator

  关于自定义校验器validator,网上的相关资料很多,如常用正则检查的validator。

  规则定义方法:

   'formData.loginName': [   {required: true, message: "登录名不能为空", trigger: 'blur'},   {validator:loginNameValidator, trigger: 'blur'}   ],

  表示'formData.loginName'属性使用了loginNameValidator的校验器。考虑到代码的复用,一般将自定义的校验器独成了js文件,便于其它页面或项目使用。

  在/src/common/目录下,创建validator.js文件,代码如下:

/* 登录名校验 */export function loginNameValidator(rule, value, callback){ const reg= /^[a-zA-Z][\w-. @]*$/; if(value == '' || value == undefined || value == null){ callback(); }else {  if (!reg.test(value)){  callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); }else {  callback(); } }}

  在vue文件中导入此validator.js文件:

import {loginNameValidator} from '@/common/validator.js'

  如果需导入多个外部校验器,则在{}中包含多个,如{loginNameValidator,passwordValidator}。

  这里有个小坑,稍微提一句。

  根据目录结构,我先使用下列语句:

import {loginNameValidator} from '../../../common/validator.js'

  结果,编译错误,说找不到'../../../common/validator.js'文件,于是各种路径表示方法尝试,均告失败。最后还是使用改用@通过了,因为/bulid/webpack.base.conf.js中配置了alias,指示@表示src目录。

  回到自定义validator,其形式为:

function ValidatorFuncName(rule, value, callback)

  方法名,随意指定。

  实际上,其完整形式为:

function ValidatorFuncName(rule, value, callback, source, options)

  参数含义如下:

  • rule:指向规则的对象,可以在方法代码中,加入第一句:

    console.log(rule);

    可将rule参数打印出来看,就是本条规则的对象数据。

  • value:属性的值,该值为需要校验的值。

  • callback:指向校验结束的回调函数,如果校验通过,调用callback(),如果未通过,一般使用下列形式:

callback(new Error('具体的提示信息'));

  或带参数的提示:

return callback(new Error(`${rule.field} must be lowercase alphanumeric characters`));

  注意,字符串格式化,不是使用单引号括起来,而是用"~"符号括起来。

  也可以使用async-validator官网(https://github.com/yiminghe/async-validator)的方法:

util.format('%s must be lowercase alphanumeric characters', rule.field),

  util文件中包含format方法,这个util.ts文件,在官网的src/目录下,这是个ts文件,可以类似做一个公共方法。

  实际上,可以返回一个Error的数组,即errors,如:

  const errors = [];  errors.push(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号'));  errors.push(new Error('3444要求为:英文'));  return callback(errors);

  但从实际效果看,表单只显示了第一行的提示,估计Element的表单不支持显示多行错误信息。

  • source:为调用校验的属性对象,可以打印出来看一下。
  • options,附加参数,主要是预定义的消息格式,也可以打印出来看一下。

  更复杂的校验器,可以携带参数,如:

// 整数范围值校验export const intRangeValidator = (min, max) => (rule, value, callback) => { var isInRange = (value >= min) && (value <= max); const reg = /^-?\d+$/; var isInt = reg.test(value); if (isInRange && isInt){ return callback(); }else{ return callback(new Error(`要求是在${min}到${max}的整数 [${min}, ${max}]`)); }}

  使用方法:

  'formData.age': [  {validator: intRangeValidator(1,100), trigger: 'blur'}  ], 

  表示,formData.age属性的取值范围为1-100的整数。

  自定义校验器validator提供了自由发挥的空间,可以使用正则匹配、数值计算和比较等运算等,进行复杂的校验,因此比较常用。但用自定义校验器validator,有时会显得过于繁琐。

  自定义校验器validator不一定要放置在外部文件中,也可以放置vue文件中。

  放置在data中,但不被return所包括的位置,尾部没有逗号。

const loginNameValidator = (rule, value, callback) => { const reg= /^[a-zA-Z][\w-. @]*$/; if(value == '' || value == undefined || value == null){ callback(); }else {  if (!reg.test(value)){  callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); }else {  callback(); } }}

  或直接在规则中定义:

   'formData.loginName': [   {required: true, message: "登录名不能为空", trigger: 'blur'},   {validator(rule, value, callback){    const reg= /^[a-zA-Z][\w-. @]*$/;    if(value == '' || value == undefined || value == null){    callback();    }else {     if (!reg.test(value)){     callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号'));    }else {     callback();    }    }       },    trigger: 'blur'}   ],

3.3、类型type

  类型type的基本用法如下:

  'formData.age': [  {type: 'integer',message: "值要求为整数",trigger: 'blur'},  ],

  类型也是一个规则项,如不符合类型要求,则提示错误信息。

  规则支持的类型如下:

  • string,字符串类型,这是默认类型。如不指定type,默认就是string。
  • number,数字类型。包括整数和小数。
  • integer,整数类型。
  • float,浮点数类型,此时不能为整数,必须有小数点。
  • boolean,布尔类型,true/false值。
  • array,数组类型。
  • object,对象类型,不能为数组。
  • enum,枚举类型,然后需要声明该枚举类型。
  • method,函数(或方法)类型。
  • regexp,正则类型,必须是一个合法的正则表达式,可以通过new RegExp来创建。
  • date,日期类型,值必须可以转为有效日期值。
  • url,url类型,值需要符合url格式。
  • email,email类型,符合邮箱格式格式。
  • hex,16进制表示的形式。如0xFF12。
  • any,任意类型,不限制。

  这里的url和email类型,可以直接用于相关含义的属性校验,如:

   'formData.email': [   {type: 'email', message: "必须符合邮箱地址格式",trigger: 'blur'}   ], 

  日期类型也比较有用,这些内置类型,使得我们可以不必通过自定义校验器validator来处理。

  对于数值类型(number,integer,float)以及boolean型,由于input输入的都为字符串,因此必须进行类型转换,否则校验通不过。这里涉及到transform的用法。

3.3、数据转换transform

  transform是一个钩子函数,在开始验证之前可以对数据先处理后验证。如下面示例:

  'formData.age': [  {   type: 'integer',   message: "值要求为整数",   trigger: 'blur',   transform(value){return parseInt(value);},  },  ],

  经过transform类型转化后,formData.age属性的校验规则就能正常使用了,否则总是通不过类型校验。(这里实际上有点问题,如允许输出12ab这种形式的值,parseInt得到值为12)

  对于类型转换,transform还有更简洁而严格的表述:

 'formData.age': [ {  type:'integer',  message: "值要求为整数",  trigger: 'blur',  transform:Number}, }, ],

  表示转换为数字类型,这样就行了。值为1.2或12ab都不能通过校验。

  transform除了类型转换外,还可以进行其它处理,如:

   'formData.age': [   {type : 'string',pattern:/1/,message: "值要求为1-100的数",transform(value){return parseInt(value)>=1 && parseInt(value)<=100 ? "1" : "0";},}   ], 

  等于某个值:

   'formData.age': [   {type : 'string',pattern:/1/,message: "值要求必须为50",transform(value){return value == "50" ? "1" : "0";},}   ], 

  不等于某个值:

  'formData.age': [  {type : 'string',pattern:/0/,message: "值要求不能为50",transform(value){return value == "50" ? "1" : "0";},}  ], 

3.4、数值范围Range

  Range不是规则的属性字段,其通过min和max属性来体现。

  如果类型type为string或array,则min和max表示长度。

  如果类型type为数值类型(number,integer,float),则min和max表示值的范围。如:

 'formData.age': [ {  type:'integer',  message: "值要求为1-100的整数",  min: 1,  max:100,  trigger:'blur',  transform:Number, }, ],

  这样,范围校验直接可使用规则的内置属性,在规则中进行描述,也无需用intRangeValidator校验器和正则匹配方式了。

3.5、枚举值

  枚举值类型的用法示例:

   'formData.idType': [   {    type: 'enum', enum: [2,4,6], message: `结果不存在`, trigger: ['change', 'blur'], transform(value) {return Number(value) * 2},   },   ], 

  或:

  'formData.gender': [  {   type: 'enum', enum: ['male','female'], message: `结果不存在`, trigger: ['change', 'blur'],  },  ], 

  使用有下列问题:

  • 反应比较迟钝,就是一开始几次输入,没有校验,一旦有校验了,后面都就可以了。
  • 对于后一种情况,即范围为字符串的集合,校验正常。对于前一种情况,即范围为整数型的,0也通过校验了,导致任意字符串也通过校验了,这是一个bug。

  因此,也可以利用字符串枚举值,来校验范围:

   'formData.age': [   {    type : 'enum',    enum:["1"],    message: "值要求为1-100的数",    transform(value){     if (!isNaN(value)){      return parseInt(value)>=1 && parseInt(value)<=100 ? "1" : "0";     }else{      return "0";     }    	}   },   ], 

  注意:此时1e3,9e811被认为是通过校验了,因为parseInt函数只取e前面的数字,而isNaN认为是数字。看来还是需要与正则规则配合才行。

3.6、正则Pattern

  pattern属性,就是正则表达式匹配校验规则,如:

   'formData.loginName': [   {required: true, message: "登录名不能为空", trigger: 'blur'},   {pattern:/^[a-zA-Z][\w-. @]*$/,    message:'要求为:英文字母开头,后续为字母数字及_-. @符号',    trigger: 'blur'}   ],

  效果与之前的loginNameValidator校验器相同,区别在于loginNameValidator可以复用,保持一个正则校验,如需修改,只需改动一处。而使用pattern则不然。但使用pattern可以少写自定义校验器,给了用户一个选择。

  使用pattern属性,可以进行等于某个值某个值的校验。

  等于某个值:

{pattern:/120/,message:'必须必须为120',trigger: 'blur'}

  关于js正则表达式,可先用js正则表达式在线测试工具测试一下,检查是否达到预期效果。js正则表达式在线测试地址:https://c.runoob.com/front-end/854。

3.7、长度len

  len属性,如果类型为string或array,则冷表示长度。如果为数字型,则表示数字值就是len属性值。

  len属性与min、max属性同时出现了,len属性有更高的优先级。

  len属性,可用于格式化的字符串校验,如身份证号码长度。

  len也可用于等于某个数值的校验,如:

 'formData.age': [ {  type:'integer',  message: "值要求必须为6周岁",  len: 6,  trigger:'blur',  transform:Number, }, ],

3.8、空白whitespace

  空白表示全部由空格组成的字符串,规则的类型必须为string。如果匹配规则,则告警提示。如:

   'formData.email': [    {whitespace: true, message: '只存在空格', trigger: 'blur'}   ], 

  值为空格,会提示告警。

  如果不希望空格干扰校验,可用transform来处理:

transform(value) { return value.trim();}

3.9、i18n

  message支持i18n,即国际化处理,如集成vue-i18n,message属性的用法如下:

message: () => this.$t( 'about' ) 

  中文语言显示"关于",英文语言显示"about"。

  当然,你也可以换成任意的其它函数,如:

message: () => this.myMessageHandler(MessageId,paramValues)

4、规则校验的高级模式

4.1、异步校验器asyncValidator

  异步校验器用于远程访问,利用ajax或axios请求数据,对响应数据进行校验或对异常进行提示。

  本地页面校验,属于串行校验,逐个检查各字段的校验规则,遇到未通过即返回校验失败。

  远程校验,为异步校验,多个请求,响应时间各有不同,响应的先后次序就无法预知。

  异步校验的作用:可以将前端和后端针对相同属性字段,使用相同的校验规则,统一由后端提供校验。但这同样增加了前后端沟通和一致性维护的成本。

  目前暂时未用到异步校验器,这里用官网的示例:

asyncField1:{asyncValidator: myAsyncValidator}

  myAsyncValidator可类似validator位置放置。假设放置在data中。

const myAsyncValidator = (rule, value, callback) => {  ajax({  url: 'xx',  value: value,  }).then(function(data) {  callback();  }, function(error) {  callback(new Error(error));  }); }

  Promise异步字段校验:

 const myAsyncValidator = (rule, value) => {  return ajax({  url: 'xx',  value: value,  }); }

  区别在于Promise异步字段校验,需要使用者自己写上.then/.catch处理逻辑,不支持回调。

  异步校验,还涉及到Options属性,

options: { first: true },

  first为true,表示多个异步校验遇到第一校验失败就不再处理其它异步校验。

4.2、深层规则Deep rules

  对于对象Object或数组Array的校验,需要具体到每一个元素(成员),这里就要用到Deep rules。

  Deep rules涉及到fields和defaultField两个属性。

  如官网示例(按照习惯形式略作修改):

  对象的深层校验:

rules : { address: [{ type: 'object', required: true, options: { first: true }, fields: {  street: [{ type: 'string', required: true }],  city: [{ type: 'string', required: true }],  zip: [{ type: 'string', required: true, len: 8, message: 'invalid zip' }], }, }], name: [{ type: 'string', required: true }],};

  数组的深层校验:

rules : { roles: [{ type: 'array', required: true, len: 3, fields: {  0: [{ type: 'string', required: true }],  1: [{ type: 'string', required: true }],  2: [{ type: 'string', required: true }], }, }],};

  数组的深层校验,看起来比较傻,每个成员都要设置校验规则,对于动态数组,似乎也不知该如何设置。

  defaultField属性,使我们对字段校验规则有了统一设置的手段。此属性可以作用在校验属性字段上,也可以作用在fields上。

  例如:

rules : { urls: [{ type: 'array', required: true, defaultField: { type: 'url' }, }],};

  如果是对象数组,该如何设置?可如下方式:

rules : { persons: [{ type: 'array', required: true, defaultField:{  type: 'object',  required: true,  fields: {   address: [{    type: 'object',    required: true,    fields: {     street: [{ type: 'string', required: true }],     city: [{ type: 'string', required: true }],     zip: [{ type: 'string', required: true, len: 8,       message: 'invalid zip' }],    },   }],   name: [{ type: 'string', required: true }],       } } }],};

  数组套对象,对象套子对象,看起来有点复杂。

4.3、动态规则集

  有时候不同模式进入表单,需要应用不同的规则。如新增和编辑操作,显示同一个页面组件。但此时对页面需要校验的属性字段有所不同,如何设置?

  有两个处理方案。方案1是配置两套规则集,根据不同模式进行切换;方案2是配置总的规则集,根据不同模式抽取合适的属性字段和规则,动态构建规则集。

4.3.1、切换校验规则集

  切换校验规则集,示例代码如下:

  // data 部分  // 当前规则集  rules:{},  // 模式1规则集  rules1:{   ...  },  // 模式2规则集  rules2:{   ...  },  // methods部分  // 动态切换  // 页面初始化  init(obj,data){  this.prevForm = obj;  // 设置页面可见  this.visible = true;  // DOM更新之后执行  this.$nextTick(()=>{   // 重置当前页面的所有字段值   this.$re......

原文转载:http://www.shaoqun.com/a/859333.html

跨境电商:https://www.ikjzd.com/

FEN:https://www.ikjzd.com/w/2668

易麦:https://www.ikjzd.com/w/2048

赛兔:https://www.ikjzd.com/w/2375


-如何判断属性值是否在某个范围内,且这个范围可以任意指定?-如何判断属性值是否为某个值?-多个属性联合校验,当前属性的校验规则依赖于另一个属性的值,如何进行校验?-两种模式,进入同一个表单组件,某些栏位可以不使用校验规则,即rules的对象会有所不同。这种情况如何处理?有必要深入了解Vueelement-ui的表单校验规则。1、前言  Element-ui表单校验规则,使得错误提示可以直接在for
亚马逊 海外购:https://www.ikjzd.com/w/998
声网agora:https://www.ikjzd.com/w/2176
​突发!字节跳动或同意完全放弃TikTok股份:https://www.ikjzd.com/articles/126919
干货:分享7个亚马逊选品小妙招:https://www.ikjzd.com/articles/126918
重要|在亚马逊欧洲销售CE 标商品,若无合规负责人将被视为违法:https://www.ikjzd.com/articles/126917
"七分靠选品,三分靠运营"你选对产品了吗?:https://www.ikjzd.com/articles/126907
舌头伸进去里面吃小豆豆 使劲添啊添的流水了:http://lady.shaoqun.com/a/248217.html
女人把腿张开让男人桶 两根粗大在她腿间进进出出:http://lady.shaoqun.com/a/247508.html
女海王阵型!不告诉男朋友就勾搭富二代!数百万粉丝,Tik Tok女人,网络名人,做了很多轮:http://lady.shaoqun.com/a/410933.html
清迈的一个天桥小舒林成同志,被居民举报:http://lady.shaoqun.com/a/410934.html
女人为什么选择"暧昧"?倾听中年妇女的心声:http://lady.shaoqun.com/a/410935.html
独立站高昂流量成废品,如何操作才能起死回生?(上):https://www.ikjzd.com/articles/146487

No comments:

Post a Comment