【实战分享】解决Vue3中多表单同时提交的数据验证问题,一次搞定!

文章讲述了在Vue项目中,如何处理由多个动态组件构成的复杂表单,其中各组件需同时验证并提交。作者通过初始化验证结果、暴露组件方法和管理切换逻辑,成功解决了在组件切换时表单验证数据丢失的问题。
摘要由CSDN通过智能技术生成

项目场景:

页面由三个tabs切换的表单数据,包括各种计算逻辑等复杂的交互,但是三个表单数据需要同时填写完成后,一并提交,使用到component动态组件。


问题描述

提交按钮在父组件也就是和component同级,无法拿到每个组件的表单验证结果

页面部分代码:

    <component
      :is="element[current].type"
      :addEditInfo="dataInfo"
      :key="current"
      @ruleFormRefValidateResult="ruleFormRefValidateResult"
      ref="componentRuleFormRef"
    ></component>
    <Button @click="handleBack" class="mr10" type="default">返回</Button>
    <Button @click="handleSave" :loading="draftLoading" class="mr10" type="primary" ghost>保存</Button>

原因分析:

由于页面其他组件已经被销毁,ref再去获取的时候就无法得到除了当前显示的其余组件内部方法包括表单验证数据等~


尝试解决过程:

尝试了不用component,把每个组件写到页面上,用v-show来控制对应的显示与隐藏,结果是:由于v-show是通过css的方式来进行显示隐藏切换,这样导致页面tabs切换的时候始终显示的是第一个组件,其他组件无法正常切换显示。这时候可能有小伙伴会说,v-if呗,v-if确实能解决页面显示隐藏的正常切换,但。。。这又回到了最初的问题,页面始终只会有一个组件未被销毁。
尝试另一种方案:外层套一个form包裹,内部使用formitem, 依然会有切换时已被销毁掉的数据拿不到的情况


最终解决方案:

1.先在component组件初始化每个组件的验证结果都为false

// 初始每个子组件的验证结果,如果不是必填的表单默认值可以直接为true
const childFormResult = ref({
  infoValidResult: false,
  leaseAgreementValidResult: false,
  feeItemsValidResult: false, 
});

2.在每个组件命名一个相同的方法,并在里面处理每个页面的最终逻辑和数据,包括表单的验证结果等
某一组件示例:

const exposeFormRefValidateResult = () => {
  ruleFormRef.value.validate(valid => {
    emits('ruleFormRefValidateResult', {
      validResult: valid,//表单验证结果
      addEditInfo,//这是页面数据
      typeKey: 'leaseAgreementValidResult',//对应组件的标识
    });
  });
};
defineExpose({
  exposeFormRefValidateResult,
});

3.component组件切换tabs时拿到exposeFormRefValidateResult方法,并处理逻辑,便于后面提交使用

/**
 * @description: 切换tab
 * @param key
 */
const changeTab = (key: string) => {
  componentRuleFormRef.value.exposeFormRefValidateResult();
};
/**
 * @description: 接收子组件数据
 * @param result 
 */
const ruleFormRefValidateResult = (result) => {
  const { typeKey, validResult, addEditInfo } = result;
  childFormResult.value[typeKey] = validResult;//赋值组件的验证结果
  //addEditInfo是每个组件页面的表单数据,根据实际情况看是否需要
};

4.提交

const handleSave = async () => {
  componentRuleFormRef.value.exposeFormRefValidateResult();
  const allResult = Object.values(childFormResult.value).every(function (value) {
    return value === true;
  });
    if (allResult) {
     //全部表单数据都通过啦~~
     //可以发起请求...
  } else {
    if (!childFormResult.value.infoValidResult) return showMessage('根据实际业务提示语!', 'error');
};

到这儿就完美搞定啦~

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值