问题描述
我的页面用antd的Form写的,如下:
在渲染的时候大部分Form.Item不会被渲染出来。这在使用的时候倒是没什么问题,但是到了提交的时候,因为Form.Item没有渲染,哪怕未选中的那些项有错误的值,也因为没有触发校验而顺利提交了。
当然,下下策是最后提交的时候手动遍历数组然后自己写校验代码也可以,但是这极不灵活而且一定程度上失去了使用Form的意义——我用它不就是干这个的吗,那校验我又自己重写了,用它干嘛。
问了一下身边的人,答曰,你让他全部渲染出来不就好了。
……
在不短的沉默后,我们都笑了。
尝试
我知道多节点渲染的优化解决方案里就有虚拟滚动,就是只渲染需要展示的节点。
但是我很好奇这个页面全部渲染的情况下能有多卡。
数据如下:
就算不看数据,就是随便做一个操作感觉上就像一个世纪那么漫长。
所以我还是改回来了。
解决
我想到一个好办法。
提交的时候覆盖上一个蒙层,弄一个loading告诉用户在校验中。
然后依次去选中,然后每次选完了就去调用form.validateFields()
。
如果出错了,刚好停下来,让用户去改错误。
代码
const onFinishFailed = ({ errorFields }) => {
if (errorFields?.length) {
errorFields.forEach(
(cur) => cur?.errors[0] && message.error(cur?.errors[0]),
);
}
};
const clickEveryPlayCheckError = async (values, curIndex = 0) => { // 依次点击,依次校验,发现有错误就停下来报错
if (values?.playSteps?.length <= curIndex) return true;
console.log('submit validating...', curIndex);
editPlayRef?.current?.updateActiveItem(values?.playSteps[curIndex]); // 更换当前展示的item
await new Promise((resolve) => setTimeout(resolve, 10));
try {
await form.validateFields();
return clickEveryPlayCheckError(values, 1 + curIndex);
} catch (error) {
console.log('err', error);
onFinishFailed(error);
}
return false;
};
const onFinish = async (values) => {
console.log("submit", values); // eslint-disable-line
setSubmitValidating(true);
const validateRes = await clickEveryPlayCheckError(values);
setSubmitValidating(false);
if (!validateRes) return;
// ……
}
效果如下