uniapp 自定义校验
程序员文章站
2022-06-19 15:44:12
之前做app项目关于自定义检验方面的内容在此记录一下需求:在app端实现跟pc端相同的校验规则前提:pc端使用的是elementui表单校验在自己动手写之前,先看了一下插件市场关于自定义检验的表单组件,一是觉得不是很好用,二是当时决定尽量少用插件,因此决定自己手写一个自定义校验的方法,在项目中使用。关于pc端elementUI检验规则是如下这种写法:formRules = { inventoryYear:[ {required:true,message:'请...
之前做app项目关于自定义检验方面的内容在此记录一下
需求:在app端实现跟pc端相同的校验规则
前提:pc端使用的是elementui表单校验
在自己动手写之前,先看了一下插件市场关于自定义检验的表单组件,一是觉得不是很好用,二是当时决定尽量少用插件,因此决定自己手写一个自定义校验的方法,在项目中使用。
关于pc端elementUI检验规则是如下这种写法:
formRules = {
inventoryYear:[
{required:true,message:'请选择盘点年份',trigger:'change'}
],
inventoryMonth:[
{required:true,message:'请选择盘点月份',trigger:'change'}
],
accessoryMaterialName:[
{required:true,message:'请输入配件材料名称',trigger:'change'}
],
qualityStatus:[
{required:true,message:'请选择质量状况',trigger:'change'}
],
inventoryNumber:[
{required:true,message:'请输入盘点数量',trigger:'change'},
{pattern: /^\d+\.?\d{0,8}$/, message: "盘点数量只能为数值并保留八位小数",trigger: "change"},
]
}
为了可以方便直接使用,决定在此基础上写一套关于app的自定义校验规则。
分析:当表单完成输入时,数据是如下这种格式
baseInfo = {
inventoryYear:1,
inventoryMonth:1,
accessoryMaterialName:1,
qualityStatus:1,
inventoryNumber:1
}
因此只需要将校验规则中的规则依次拿出与数据进行匹配是否满足即可。
需要解决的问题:
1.只要有一个不满足就不向下继续匹配,并提示有数据不符合要求
2.兼容elementui的规则配置,require表示是否必填,pattern表示正则匹配,validator表示自定义校验
3.由于该项目是否必填,存在a填了,b必填,a没填,b可不必填这种情况,因此需要特殊处理
4.存在数据里面存在数组的情况,数组里面的数据如何校验,例如
a = {
b: 1,
c: 2,
d: [
{ e: 3, f: 4 }
]
}
5.如何按照顺序校验
解决思路:
1.配置规则时,配置一个order数组,按照数组里面的顺序进行排序校验,如:
export const accessoriesInventoryRules = {
a:[
{required:true,message:'请选择'}
],
b:[
{required:true,message:'请选择'}
],
order:['a','b''] // 先校验a再校验b
}
2.配置规则时,将数组里面的规则配置在一个对象中,同样该对象中也需要一个order指明排序,如:
export const accessoriesInventoryRules = {
a:[
{required:true,message:'请选择'}
],
b:{
a: [
{ required: true, message: "请输入配件材料名称"}
],
b: [
{ required: true, message: "请选择质量状况"}
],
c: [
{ required: true, message: "请输入盘点数量"}
],
order:['a','b','c'] // a、b、c轮流校验
},
order:['a','b'] // 先校验a再校验b
}
3.关于require的特殊处理,我希望配置规则时可以这样配置,如:
export const accessoriesInventoryRules = {
a:[
{required: function(){
return this.b != 1 // 当前的this指向当前这个对象,可以根据b的不同决定a是否必填
}, ,message:'请选择'}
],
b: [
{ required: true, message: "请选择质量状况"}
],
order:['a','b']
}
4.具体代码分析如下
/**
*
* @param {*} baseInfo 当前的表单数据
* @param {*} baseInfoRules 表单数据的配置的校验规则
* @param {*} isCheckRequire 这个区分是否需要校验必填项,项目中保存不需要校验必填项,提交时需要校验
* 如果校验没有通过返回一个true
*/
export const validator = function(baseInfo,baseInfoRules,isCheckRequire){
// 先获取校验顺序
var order = baseInfoRules.order;
if(order){
// 由于第一点有一个不满足即不向下校验,因此使用some查找是否存在不满足的情况
return order.some(item=>{
// 拿出校验规则
let ruleItems = baseInfoRules[item];
if( Array.isArray(ruleItems) ) {
// 将校验规则依次与当前数据进行匹配,如果有不满足某个校验规则即返回
return ruleItems.some( rule => {
// 如果匹配到当前配置了必填,进行必填校验,方法在下
if( rule.required ) {
return requireRule(rule,baseInfo[item],baseInfo,isCheckRequire)
}
// 如果匹配到当前配置了正则,进行正则校验,方法在下
else if( rule.pattern ){
return patternRule(rule,baseInfo[item],baseInfo)
}
// 如果匹配到当前配置了自定义校验,进行自定义校验,方法在下
else if ( rule.validator ){
return customRule(rule,baseInfo[item],baseInfo)
}
})
}
/*配置校验规则时,如果是数组里面的校验会被包含在一个对象中,示例见上*/
else if ( ruleItems.constructor == Object ){
// 同理,将数组里面的数据依次拿出进行校验
if(Array.isArray(baseInfo[item]) && baseInfo[item].length > 0){
return baseInfo[item].some(detailItem=>{
return validator(detailItem,baseInfoRules[item],isCheckRequire)
})
}else if(baseInfo[item].constructor == Object) {
return validator(baseInfo[item],baseInfoRules[item],isCheckRequire)
}
}
// 没有配置校验规则
else {
console.log(111);
}
})
}
}
// 必填校验
function requireRule(item,value,baseInfo,isCheckRequire){
let flag = item.required;
// 这里做一个特殊处理,如果require传人的是一个function,将function中的this指向该数据所在的对象,并执行该方法
if( typeof item.required == 'function' ){
flag = item.required.call(baseInfo);
}
if(isCheckRequire){ // 不校验必填
flag = false;
}
// 如果校验没有通过,提示信息并返回
if( flag && ( value === '' || value === undefined ) ){
uni.showToast({
title: item.message,
duration: 1000,
icon:'none',
mask:true
});
return true;
}
return false;
}
// 正则校验
function patternRule(item,value,baseInfo){
let pattern = item.pattern;
// 正则匹配没有通过,则提示信息并返回
if(!pattern.test(value) && value){
uni.showToast({
title: item.message,
duration: 1000,
icon:'none',
mask:true
});
return true;
}
return false;
}
// 自定义校验
function customRule(item,value,baseInfo){
let validator = item.validator;
// 自定义校验,同理将function中的this指向该数据所在的对象,并执行方法,不满足提示信息并返回
if(!validator.call(baseInfo) && value){
uni.showToast({
title: item.message,
duration: 1000,
icon:'none',
mask:true
});
return true;
}
return false;
}
用法如下:
// 1.数据格式
baseInfo = {
checkSourceCode: '111',
materialCodeNumber:'222',
checkDate:'222',
contractList:[
{ number: 2 }
]
}
// 2.配置规则
// 自定义校验
function validNumber(){
if (this.number > 0 && this.number <= Number(this.tempNumber)) {
return true
} else {
return false
}
}
function validTransferPrice(){
if (this.transferPrice > 0 && this.transferPrice <= Number(this.purchasePrice)) {
return true;
} else {
return false;
}
}
export const getContractListRules = {
checkSourceCode:[
{required:true,message:'请选择'}
],
materialCodeNumber:[
{
required:function(){return this.checkSourceCode},
message:'必填项不能为空'
}
],
checkDate:[
{required:true,message:'请选择点验日期'}
],
contractList:{
//数量
number: [
{ required: false, message: "请输入数量",},
{pattern: /^\d+\.?\d{0,8}$/, message: "数量只能为数值并保留八位小数"}
],
order:['number']
},
order:['checkSourceCode','materialCodeNumber','checkDate','contractList'],
}
// 调用方法
validator(baseInfo,getContractListRules)
本文地址:https://blog.csdn.net/qq_42173653/article/details/112518345