动态组件优化多步骤表单提交场景

131 阅读1分钟

父组件

<template>
 <div>
   <el-steps :active="currentStep">
     <!-- 步骤定义... -->
   </el-steps>
   <keep-alive>
     <component 
       :is="currentStepComponent" 
        :ref="`stepForm${currentStep}`"
        :key="currentStep"
      ></component>
    </keep-alive>
    
    <el-button @click="submitForms">提交</el-button>
  </div>
</template>
export default {
 data() {
   return {
     currentStep: 0,
     // 假设每个步骤组件的ref都遵循特定命名规则,如stepForm1, stepForm2...
   };
 },
 methods: {
   submitForms() {
      let isValid = true;
      for (let i = 1; i <= this.totalSteps; i++) { // 假设totalSteps是你步骤的总数
        const formRef = `stepForm${i}`;
        if (this.$refs[formRef]) {
          isValid = isValid && this.$refs[formRef].validate();
        }
      }
      
      if (isValid) {
        // 所有表单验证通过,可以发送请求
        this.sendRequest();
      } else {
        console.log('表单验证未通过,请检查!');
      }
    },
    sendRequest() {
      // 发送请求的逻辑
      console.log('所有表单验证通过,发送请求...');
    },
  },
};

子组件

每个步骤组件内部需要实现自己的表单验证逻辑,并暴露一个 validate 方法供父组件调用。以下是一个简单的步骤组件示例:

export default {
 data() {
   return {
     // 表单数据...
   };
 },
 watch:{
 
 },
 methods: {
   validate() {
      // 这里应该调用el-form的validate方法并返回Promise
      return this.$refs['yourFormRef'].validate((valid) => {
        return valid;
      });
    },
  },
};

提交表单

// 提交表单并不建议,父组件通过refs直接去获取子组件的数据这样并不是vue使用的最佳实践,这会违反组件封装的原则

子组件

1. 在子组件中暴露获取表单数据的方法

首先,确保每个步骤组件(子组件)都有一个公开的方法用于获取该组件内的表单数据。例如,如果您的子组件是用 Vue 编写的,可以在子组件中添加如下方法:

export default {
3  // ...
4  methods: {
5    getFormData() {
6      // 假设 this.form 是维护表单数据的对象
7      return this.form;
8    }
9  }
10  // ...
11}

父组件

2. 父组件收集所有子组件的表单数据

在父组件中,您可以遍历所有步骤组件的引用(通过 $refs 访问),并调用它们的 getFormData 方法来收集数据。这里假设您已经有了一个触发提交表单请求的方法,比如叫 submitForm

methods: {
 submitForm() {
   const formDataArray = [];
   
   // 假设 currentStep 是当前步骤,stepForms 是所有步骤组件的引用数组
   for (let i = 0; i <= this.currentStep; i++) {
     const stepRefName = `stepForm${i}`;
     if (this.$refs[stepRefName]) {
        const formData = this.$refs[stepRefName].getFormData();
        formDataArray.push(formData);
      }
    }

    // 合并所有表单数据,这里简单合并为一个数组,实际可能需要更复杂的逻辑来组合数据
    const allFormData = formDataArray.reduce((acc, curr) => ({ ...acc, ...curr }), {});

    // 发送请求
    this.sendRequest(allFormData);
  },

  sendRequest(data) {
    // 使用axios或其他库发送POST请求
    // 示例代码,实际请替换为您的请求逻辑
    console.log('Sending form data:', data);
    // axios.post('/your-endpoint', data).then(response => {
    //   console.log('Form submitted successfully');
    // }).catch(error => {
    //   console.error('Error submitting form', error);
    // });
  }
}

stepForm是在哪里定义的

`stepForm` 是在示例中作为动态组件的引用名称使用的,用于在父组件中通过 `$refs` 访问到每个步骤组件的实例。在提供的示例代码中,它是通过动态生成的 `ref` 名称来实现的,具体体现在以下两部分:

1.  **父组件模板** 中,通过 `:ref` 绑定动态生成的引用名称,这里使用了步骤编号来构建引用名,确保每个步骤组件的引用都是唯一的。