1、背景
工作中会遇到用户表单提交,涉及的字段上百个,这种情况下我们一般会拆分组件。
我们使用react或者vue框架的form表单,都自带了校验的功能,如下,调用该方法页面校验不通过的编辑框会变红,并且在对应编辑框附近展示提示语。
如果涉及多个form表单,你会怎样实现同时校验呢?
checkForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
}
2、三种实现方式
执行checkForm方法,我们需要对应form渲染,可以拿到对应this.$refs[formName]。
2.1 展示所有dom
- 存储所有表单的checkForm方法,使用Promise.all执行各个form的校验
缺点:需要渲染所有dom,页面性能不好;一般情况下,我们会使用tabs组件,不同模块放在不同tab
2.2 使用js库async-validate
- 使用tabs组件,每次只渲染active的tab;
- 页面数据存在父组件,避免切换tab导致之前编辑数据丢失
- 通过js库async-validate,找到第一个校验不通过的tab,切到该tab;调用checkForm方法。
import Schema from 'async-validator'
const rules = {
userName: { type: 'string',required: true },
pass: { type: 'string',required: true }
}
const validator = new Schema(rules)
var formData = {userName: '', pass: ''}
validator.validate(formData,(errors, fields) => {
if (errors) {
console.log('验证不通过', errors, fields)
return
}
console.log('验证通过')
})
3.3 渲染改动过的tab
接手一个老项目的优化
现状:共有16个页签,每次只渲染active的tab。每个tab的数据独立,都有对应的保存接口;
痛点:每次页签切换都需要点击保存,不然切换页签原编辑数据丢失;点击提交之前,需要逐个点击保存;
需求:切换页签原编辑数据保留;增加总的保存按钮,对需要保存的tab一起保存;
分析:
方案一:展示16个tab,保存时同时执行16个页签的checkForm方法;
- 缺点:页面开销太大,渲染dom较多;保存时有些页面没编辑不需要保存
方案二:切换tab前执行checkForm方法;
- 缺点:用户体验不好,必须编辑完当前tab才能切换
方案三:使用js库async-validate;
- 缺点:代码改动较大,需要提取所有表单的rules和formData对象
方案四:展示所有编辑过的表单
- 数组cachedList存储所有编辑过的表单;cachedList中非active的tab通过css来隐藏展示,非cachedList的tab不渲染;
- 切换tab判断当前页面是否编辑过(vue项目可以watch formData;react项目可以使用this.props.form.isFieldTouched或者通过onValuesChange)
- 如果没有编辑则不存储,否则用 saveMap 存储该tab的保存函数,cachedList存储该tab的key;
- 点击总的保存按钮,依次执行该saveMap的保存方法,删除校验保存通过的tab数据,并且切换到未校验通过的tab下
欢迎关注我的前端自检清单,我和你一起成长