前言
在PC端项目中,经常会遇到新增或编辑保存功能单据页面,通常由表单(
header
)、表体(body
)、脚部(footer
)三部分组成。脚部包含多个保存按钮,如存草稿、保存。然而,点击这些按钮并不立即触发接口请求,而是需要前端进行静态校验。只有在静态校验通过后,才会触发接口请求并执行后续逻辑。针对这种场景,我们需要思考如何简化繁琐的静态校验流程。
场景
- 头部必填项校验:
类型、编号、日期
- 表体校验必填项校验:
表体列表没有 有效值校验
表体列表数据哪项不为空就金额字段是否有值进一步校验
我们模拟了一个稍微不算复杂的场景,我们先按照我们的正常操作实现,使用vue2为例,template 我们略去
js
<script>
export defalt {
data(){
return {
form:{
type:'',
code:'',
date:null
},
// 生成30条 空数据
list :Array.from({length: 30},(_,i)=>{
return {
rowNum: i + 1,
money:'',
name:''
}
})
}
},
methods:{
// 静态校验
vaild(){
if(!this.form.type){
alert('请选择类型')
return false
}else if(!this.form.code){
alert('请输入编号')
return false
} else if(!this.form.date){
alert('请选择日期')
return false
} else if(!this.list.filter(i=>i.name !== '').length){
alert('表体没有有效数据,无法保存!')
return false
} else if(!(this.list.filter(i=>i.name !== '').every(i=>i.money))){
alert('有效数据对应的金额没有输入')
return false
}
return true
},
// 存草稿
draft(){
if(this.vaild()){
// 调用保存草稿的接口
}
},
// 保存
save(){
if(this.vaild()){
// 调用保存的接口
}
}
}
}
</script>
在我遇到的复杂项目中,
vaild
部分的代码最多有几百行代码校验,最少十来行代码,其实我们这种优化只有在较为复杂的前端静态校验才能体现出优势,针对以上场景案例,我们重点是优化 静态校验vaild
函数里面的校验代码,使其更加易于维护
方案
我们首先编写一个同步校验多个条件的函数,来支撑我们的优化
js
/**
* @description 同步验证多个条件函数
* @param { Array } vaildList 验证列表
* @param { Object } commonParamMap 公共参数对象
* @param { Function } errCallBack 错误时的回调
* @returns function
*/
function syncCheck(vaildList = [], commonParamMap = {}, errCallBack){
return function (successCallBack){
let ret = null
for (let i = 0; i < vaildList.length; i++) {
const item = vaildList[i]
if( typeof item === 'function'){
const result = item(commonParamMap)
if(result) {
ret = result
break
}
}
}
if(ret){
errCallBack && errCallBack(ret)
} else {
successCallBack && successCallBack()
}
}
}
示例
示例使用vue2为例
js
<script>
export defalt {
data(){
return {
form:{
type:'', // 类型
code:'', // 编号
date:null // 日期
},
// 生成30条 空数据
list :Array.from({length: 30},(_,i)=>{
return {
rowNum: i + 1,
money:'',
name:''
}
})
}
},
mounted () {
// 保存前的校验函数
this.vaildBeforeSave = syncCheck(
// 校验函数数组。从上往下依次校验,哪个校验返回错位信息就终止,携带错误提示信息走到错误处理函数
[
({ type })=>{
if(!type()) return '请选择类型'
},
({ code })=>{
if(!code()) return '请输入编号'
},
({ date })=>{
if(!date()) return '请选择日期'
},
({ list })=>{
if(!list().filter(i=>i.name !== '').length) return '表体没有有效数据'
},
({ list })=>{
if(list().filter(i=>i.name !== '').every(i=>i.money))) {
return '有效数据对应的金额没有输入'
}
}
],
// 校验函数数组 内部需要解构的数据,在这里进行映射,校验函数需要什么就解构什么
{
type:()=>this.form.type,
code:()=>this.form.code,
date:()=>this.form.date,
list: ()=> this.list
},
// 校验列表数组一旦有错误信息返回,则会进入到这里。并返回对应的错位提示信息
(errMsg)=>{
alert(errMsg)
})
},
methods:{
// 存草稿
draft(){
this.vaildBeforeSave(()=>{
// 调用保存草稿的接口
})
},
// 保存
save(){
this.vaildBeforeSave(()=>{
// 调用保存的接口
})
}
}
}
</script>
我们通过 同步验证多个条件函数
syncCheck
把校验条件、校验函数需要的变量、校验不通过的处理进行有效的组织起来,形成一条有效且可易于维护的线路,达到我们的化繁为简
结语
我们项目中出现该场景的情况还是比较多的,希望对大家有用,如有疑问,欢迎留言,有更好的 idea,欢迎一起讨论,感谢
24年往期文章:
前端 同时多次调用同个接口,如何只触发一次而不是触发多次
前端 页面不同组件内调用相同接口导致重复调用,如何只触发一次而不是触发多次