多数据提交和还原-前端解决方案
业务场景:
- 表单页面提交数据保存
- 再次打开此页面请求之前保存的数据,编辑保存
问题:
- 数据量太大了,有几百个输入框,还有单选,多选,文本域,下拉选项等,一值对应一字段不大可行
解决方案:
- 对于额外用途的数据(不仅仅在此页面展示),需要和后端定义明确的字段
- 仅在当前页面展示的数据,用 对象转字符串 保存,对象用于存储只在当页展示的数据
具体实现方法(以vue为例):
原数据生产方法:用于返回一个json对象,在数据还原的时候,能找到在页面中所处的位置
function createOriginData (num) {
const data = {}
for (let i = 0; i <= num; i++) {
data[i] = ''
}
return data
}
数据格式:
data () {
return {
formVal: {
// 不需在在此定义,比如直接在页面通过 formVal.xxx 赋值的操作
confirmStr: '', // 和后台明确定义的数据,在其他地方有用
tmpStr: '', // 特殊情况需要定义的数据,防止页面报错
tmpArr: [], // 用于页面的数组系列的数据
createObj: createOriginData(10), // 用于仅在当页展示的数据
}
}
}
html:
// 可以开始不在formVal设置默认值
<input v-model="formVal.xxx" />
// 仅在当页展示的数据
<input v-model="formVal.createObj[0]" />
...
<input v-model="formVal.createObj[10]" />
// 明确定义的数据
<input v-model="formVal.confirmSte" />
// 防止页面报错,在用一些组件的情况下,这种场景下必须定义
<a-radio-group name="radioGroup" v-model="formVal.tmpStr">
<a-radio value="aaa">aaa</a-radio>
<a-radio value="bbb">bbb</a-radio>
</a-radio-group>
// 用于数组的接收的场景,比如
<a-checkbox-group v-model="formVal.tmpArr" >
<a-checkbox value="aaa">aaa</a-checkbox>
<a-checkbox value="bbb">bbb</a-checkbox>
</a-checkbox-group>
数据整理提交:
const formVal = Object.assign({}, this.formVal)
// 此操作主要用于在把对象转字符串
Object.keys(formVal).forEach((k) => {
if (typeof formVal[k] === 'object') {
formVal[k] = JSON.stringify(formVal[k])
}
})
数据还原:
methods: {
toRestore () {
const _this = this
const ajaxData // 假设此数据为ajax返回的数据,此数据的k值为之前提交数据的数据
Object.keys(ajaxData).forEach(k => {
if (ajaxData[k]) { // 只有当有值的情况下,才能赋值
try {
const obj = JSON.parse(ajaxData[k])
_this.formVal[k] = obj
} catch (e) {
_this.formVal[k] = ajaxData[k]
}
}
})
}
}
最后补充一个方法,必填数据后才能提交:
// data-no,用于标示可以为空的数据能提交, 如 <input type="text" data-no="1">
// 关于select, radio, checkbox,可以设定默认值,不在此方法中检测,或者另外检测
function checkValues (dom) {
const inputs = dom.getElementsByTagName('input')
for (let i = 0; i < inputs.length; i++) {
if (inputs[i].getAttribute('data-no')) continue
if (inputs[i].type === 'text' && inputs[i].value.trim() === '') {
inputs[i].classList.add('border-red')
inputs[i].focus()
return false
} else {
inputs[i].classList.remove('border-red')
}
}
const textareas = dom.getElementsByTagName('textarea')
for (let i = 0; i < textareas.length; i++) {
if (textareas[i].getAttribute('data-no')) continue
if (textareas[i].type === 'textarea' && textareas[i].value.trim() === '') {
return false
}
}
return true
}
总结
此方案能减少 多数据表单 开发的工作量,刚开始的时候采用的是别的方案,后来项目优化想到此方案。
---------------------------这是华丽的分割线-------------------------
总结:
1,最快的方案是:JSON.stringify(obj)
2,bug
data () {
obj: {}
}
在html中,可以 v-model=“obj.xxx”,最后数据提交
但是如果保存后还原数据再编辑(ps:js操作,obj.xxx=‘xxx’),会导致页面输入框变为不可编辑状态,还是需要在data中赋值
data()
{
obj: {
xxx: ''
}
}
3,在数据还原这步,更改了取值的方法,解决超长数字转换产生的bug
watch: {
pData (pData) {
const formVal = this.formVal
Object.keys(formVal).forEach(k => {
if (pData[k]) {
try {
if (/(\{)|(\[)/.test(pData[k])) {
const obj = JSON.parse(pData[k])
formVal[k] = obj
} else {
formVal[k] = pData[k]
}
} catch (e) {
pData[k] && (formVal[k] = pData[k])
}
}
})
}
},