多数据提交和还原-前端解决方案

业务场景:

  • 表单页面提交数据保存
  • 再次打开此页面请求之前保存的数据,编辑保存

问题:

  • 数据量太大了,有几百个输入框,还有单选,多选,文本域,下拉选项等,一值对应一字段不大可行

解决方案:

  • 对于额外用途的数据(不仅仅在此页面展示),需要和后端定义明确的字段
  • 仅在当前页面展示的数据,用 对象转字符串 保存,对象用于存储只在当页展示的数据

具体实现方法(以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])
        }
      }
    })
  }
},