如何记录验证element后台管理系统中表单(表格?)的修改痕迹
大家好我是极速网吧的黒网吧天才少年,主要打1号位,这篇文章记录一下工作中遇到的一个比较有意思的需求,防止下次开发的时候忘记,同时希望大佬们给点建议
最近接了个需求,要求我写一个表格,这个表格用户可以自由增加删除行以及修改行内的数据,输入的内容有一定的验证要求,同时记录下用户的操作,在上传数据的时候提示用户进行了哪些操作。如图:
后端返回以及要求数据结构:
const tableList = [{
section_name: "老八",
section_id:1
grade_list: ["臭豆腐", "俘虏", "臭撸虾", "嘎嘣脆嗲", "胡罗贝", "柠檬"]
}]
复制代码
这是表格中的内容,为数组对象,其中我们要记录修改痕迹的grade_list是不带id标识的,最终要求返回的数据也跟这个一致。
分析思路
记录修改痕迹,我们只需要在进入弹窗的时候记录一份原始数据,然后再比对原始数据以及提交时候的数据即可。
this.myTable = row.grade_list.map((key,index) => ({
id:index,
section_name:row.section_name,
grade_name:key
}))
this.originTable = JSON.parse(JSON.stringify(this.myTable))
复制代码
第一步:验证重复
当有重复项的时候直接阻止进入下一步,同时在表格中弹窗提示重复,样式怎么写呢?直接去element源码把el-form的验证样式复制过来即可
<!-- html内容 -->
<el-table
border
:data="myTable"
>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="section_name" label="姓名"></el-table-column>
<el-table-column label="最爱的食物">
<template slot-scope="{ row,$index }">
<div class="el-form-item" :class="{
'is-error': errorObj.hasOwnProperty($index)
}">
<div class="el-form-item__content">
<el-input v-model="row.grade_name" maxlength="10"></el-input>
<transition name="el-zoom-in-top">
<div
v-if="errorObj.hasOwnProperty($index)"
class="el-form-item__error"
>
{{errorObj[$index]}}
</div>
</transition>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="{ row,$index }">
<el-button @click="delClass(row,$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- js内容 -->
<script>
需要的data:
data(){
return{
myTable:[],
originTable:[],
tempRow:{},
//验证类
validateState:'error',
errorObj:{},
}
}
绑定在保存按钮点击事件上的方法:
putGrades(){
...
//去空
this.myTable = this.myTable.filter(key=> key.grade_name.trim() !== '')
// 验证重复,new一个名字为键序号数组为值的map,序号的length大于1的时候说明有重复
let map = new Map()
this.errorObj = {}
this.myTable.forEach((key,index)=>{
//遇到重复的名字,重新把名字对应的序号
if(map.has(key.grade_name)){
let oldVal = map.get(key.grade_name)
map.set(key.grade_name,[...oldVal,index])
return
}
map.set(key.grade_name,[index])
})
map.forEach((value)=>{
if(value.length > 1){
value.forEach(key=> {
//存入重复项以及验证错误的原因
this.$set(this.errorObj,key,'老八不喜欢重复的食物!')
})
}
})
//有重复阻止发送请求
if(Object.keys(this.errorObj).length !== 0) return
...
}
</script>
复制代码
因为错误信息errorObj因为不确定有多少项,所以没法在data中直接写上让vue动态绑定,所以在方法中用了vue.set
的方法手动来动态绑定,通过数组中的index来保证与原数组一一对应的关系。通过这个思路,我可以通过写其他的方法来验证其他不同的规则,比如是否含有字母、手机号规则等,只需要遍历数组一次,将不符合规则的index以及错误信息存入errorObj即可。
第二步:记录修改痕迹
记录修改痕迹,需要先区别新增项与原始数组中的项,我在原始数组的每一项中都添加一个id,id的值跟index一致,新增项中则没有id。这样就能将新增与原有区分开来,如此只需两步就可以记录下修改痕迹了。
ps:“新”代表要提交的数组,“旧”代表我们拷贝的那份数组
1:判断新旧是否有重名,有重名的先直接去掉,属于不变的组
2.1:判断新旧中有id的名字是否一致,不一致的部分去掉,属于修改组
2.2:判断新旧带id的数量是否一致,新中少了的部分去掉,为删除组,剩下的都是新增组
...
//第1步,判断新旧是否有重名,有重名的先直接去掉,属于不变的组
let originMap = new Map()
this.originTable.forEach(key =>{
originMap.set(key.grade_name,key.id)
})
let tempNew = this.myTable.filter((key) => {
if(originMap.has(key.grade_name)) {
originMap.delete(key.grade_name)
return false
}
return true
})
//如果全部重名即没有修改,直接返回
if(tempNew.length === 0) return
//第2.1步,判断有id的名字是否一致,不一致属于修改组
//第2.2步,判断新旧带id的数量是否一致,origin少了的部分为删除组
//第3步,剩下的都是新增组
//反转originMap中键值对
let idMap = new Map()
originMap.forEach((value,key)=>{
idMap.set(value,key)
})
let edited = new Map()
let noIDGrade = []
tempNew.forEach(key=>{
if(key.id !== undefined) {
edited.set(idMap.get(key.id),key.grade_name)
idMap.delete(key.id)
}else{
noIDGrade.push(key.grade_name)
}
})
const h = this.$createElement;
let renderEdit = []
let renderAdd = []
let renderDel = []
edited.forEach((value,key)=>{
renderEdit.push(h('p',`${key}修改为${value}`))
})
noIDGrade.forEach((value)=>{
renderDel.push(h('p',`新增:${value}`))
})
idMap.forEach((value)=>{
renderAdd.push(h('p',`已删除:${value}`))
})
//判断修改组、新增组、删除组是否为空,为空的话阻止上传
if(renderEdit.length === 0 && renderAdd.length === 0 && renderDel.length === 0) return
this.$msgbox({
title: "修改确认",
message: h("div", null, [
h(
"p",renderEdit
),
h(
"p",renderAdd
),
h(
"p",renderDel
),
]),
showCancelButton: true,
showClose: false,
confirmButtonText: "确认",
cancelButtonText: "取消"
})
...
复制代码
因为修改组必须以键值对的形式出现,即xxx修改为xxx,所以修改组我用map记录,删除组跟新增组都直接存名字的值。最后效果:
总结&求助
感觉自己写的这个东西很垃圾,遍历了很多次,用了许多额外的空间,创造了一堆数组跟map,特别是反转map键值对显得特别蠢,有没有其他思路或者写法上可以更简洁,恳请大神们给个提示,在掘金搜了一下没看到有写校验表单的相关内容。
完整的项目地址:github.com/Eating-Eati…
来源:oschina
链接:https://my.oschina.net/u/4303238/blog/3233054