多个表单使用相同的 ref 和 rules,表单验证规则不生效

在 Vue 和 Element UI 中,如果多个表单使用相同的 ref 和 rules,可能会导致表单验证规则不生效。这是因为 ref 是唯一的,多个表单共享同一个 ref 会导致冲突。

解决方法:

1. 为每个表单设置不同的 ref

为每个表单设置不同的 ref,并在验证时分别调用各自的验证方法。

示例代码:
复制代码
<template>
  <div>
    <!-- 表单 1 -->
    <el-form :model="form1" :rules="rules" ref="form1Ref">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form1.name"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('form1Ref')">提交表单 1</el-button>
      </el-form-item>
    </el-form>

    <!-- 表单 2 -->
    <el-form :model="form2" :rules="rules" ref="form2Ref">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form2.name"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('form2Ref')">提交表单 2</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      form1: { name: "" }, // 表单 1 数据
      form2: { name: "" }, // 表单 2 数据
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    // 提交表单
    submitForm(formRef) {
      this.$refs[formRef].validate((valid) => {
        if (valid) {
          alert("表单验证通过");
        } else {
          alert("表单验证失败");
          return false;
        }
      });
    },
  },
};
</script>
说明:
  • 为每个表单设置不同的 ref(如 form1Ref 和 form2Ref)。

  • 在 submitForm 方法中,通过动态传入 ref 名称来验证对应的表单。


2. 使用动态 ref

如果表单是动态生成的(例如通过 v-for 循环),可以使用动态 ref。

示例代码:
复制代码
<template>
  <div>
    <!-- 动态生成表单 -->
    <el-form
      v-for="(form, index) in forms"
      :key="index"
      :model="form"
      :rules="rules"
      :ref="`formRef${index}`"
    >
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form.name"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm(index)">提交表单 {{ index + 1 }}</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      forms: [
        { name: "" }, // 表单 1 数据
        { name: "" }, // 表单 2 数据
      ],
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    // 提交表单
    submitForm(index) {
      this.$refs[`formRef${index}`][0].validate((valid) => {
        if (valid) {
          alert(`表单 ${index + 1} 验证通过`);
        } else {
          alert(`表单 ${index + 1} 验证失败`);
          return false;
        }
      });
    },
  },
};
</script>
说明:
  • 使用 v-for 动态生成表单,并为每个表单设置动态 ref(如 formRef0、formRef1)。

  • 在 submitForm 方法中,通过索引动态获取对应的表单 ref。


3. 共享 rules 但独立验证

如果多个表单共享相同的验证规则,可以将 rules 提取到公共位置,但为每个表单设置独立的 ref 和验证逻辑。

复制代码
<template>
  <div>
    <!-- 表单 1 -->
    <el-form :model="form1" :rules="rules" ref="form1Ref">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form1.name"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="validateForm('form1Ref')">验证表单 1</el-button>
      </el-form-item>
    </el-form>

    <!-- 表单 2 -->
    <el-form :model="form2" :rules="rules" ref="form2Ref">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form2.name"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="validateForm('form2Ref')">验证表单 2</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      form1: { name: "" }, // 表单 1 数据
      form2: { name: "" }, // 表单 2 数据
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    // 验证表单
    validateForm(formRef) {
      this.$refs[formRef].validate((valid) => {
        if (valid) {
          alert("表单验证通过");
        } else {
          alert("表单验证失败");
          return false;
        }
      });
    },
  },
};
</script>
说明:
  • 共享 rules,但为每个表单设置独立的 ref。

  • 在 validateForm 方法中,通过动态传入 ref 名称来验证对应的表单。


总结

  • 如果多个表单共享相同的 ref,会导致冲突,验证规则不生效。

  • 解决方法:

    1. 为每个表单设置不同的 ref。

    2. 如果表单是动态生成的,使用动态 ref。

    3. 共享 rules,但独立验证每个表单。

4.同步验证多个表单实现思路:

  1. 为每个表单设置独立的 ref:

    • 每个表单需要有一个唯一的 ref,以便能够单独访问和验证。
  2. 使用 Promise.all 进行同步验证:

    • 将每个表单的验证方法包装成 Promise,然后使用 Promise.all 等待所有表单验证完成。
  3. 处理验证结果:

    • 如果所有表单验证通过,执行后续逻辑;如果有表单验证失败,提示错误信息。

示例代码:
复制代码
<template>
  <div>
    <!-- 表单 1 -->
    <el-form :model="form1" :rules="rules" ref="form1Ref">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form1.name"></el-input>
      </el-form-item>
    </el-form>

    <!-- 表单 2 -->
    <el-form :model="form2" :rules="rules" ref="form2Ref">
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form2.email"></el-input>
      </el-form-item>
    </el-form>

    <!-- 提交按钮 -->
    <el-button type="primary" @click="validateAllForms">提交所有表单</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      form1: { name: "" }, // 表单 1 数据
      form2: { email: "" }, // 表单 2 数据
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
        ],
        email: [
          { required: true, message: "请输入邮箱", trigger: "blur" },
          { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    // 验证单个表单
    validateForm(formRef) {
      return new Promise((resolve, reject) => {
        this.$refs[formRef].validate((valid) => {
          if (valid) {
            resolve(); // 验证通过
          } else {
            reject(new Error(`表单 ${formRef} 验证失败`)); // 验证失败
          }
        });
      });
    },

    // 同步验证所有表单
    async validateAllForms() {
      try {
        // 使用 Promise.all 同步验证所有表单
        await Promise.all([
          this.validateForm("form1Ref"),
          this.validateForm("form2Ref"),
        ]);
        alert("所有表单验证通过");
        // 在这里执行提交逻辑
      } catch (error) {
        alert(error.message); // 提示错误信息
      }
    },
  },
};
</script>

代码说明:
  1. validateForm 方法:

    • 将表单验证包装成 Promise,验证通过时调用 resolve,验证失败时调用 reject。
  2. validateAllForms 方法:

    • 使用 Promise.all 同步验证所有表单。

    • 如果所有表单验证通过,执行后续逻辑(如提交数据)。

    • 如果有表单验证失败,捕获错误并提示用户。

  3. 表单 ref:

    • 每个表单需要设置唯一的 ref(如 form1Ref 和 form2Ref)。

动态表单的同步验证

如果表单是动态生成的(例如通过 v-for 循环),可以使用动态 ref 和 Promise.all 实现同步验证。

示例代码:
复制代码
<template>
  <div>
    <!-- 动态生成表单 -->
    <el-form
      v-for="(form, index) in forms"
      :key="index"
      :model="form"
      :rules="rules"
      :ref="`formRef${index}`"
    >
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form.name"></el-input>
      </el-form-item>
    </el-form>

    <!-- 提交按钮 -->
    <el-button type="primary" @click="validateAllForms">提交所有表单</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      forms: [
        { name: "" }, // 表单 1 数据
        { name: "" }, // 表单 2 数据
      ],
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    // 验证单个表单
    validateForm(formRef) {
      return new Promise((resolve, reject) => {
        this.$refs[formRef][0].validate((valid) => {
          if (valid) {
            resolve(); // 验证通过
          } else {
            reject(new Error(`表单 ${formRef} 验证失败`)); // 验证失败
          }
        });
      });
    },

    // 同步验证所有表单
    async validateAllForms() {
      try {
        // 动态生成验证任务
        const validationTasks = this.forms.map((_, index) =>
          this.validateForm(`formRef${index}`)
        );
        // 使用 Promise.all 同步验证所有表单
        await Promise.all(validationTasks);
        alert("所有表单验证通过");
        // 在这里执行提交逻辑
      } catch (error) {
        alert(error.message); // 提示错误信息
      }
    },
  },
};
</script>

总结

  • 使用 Promise.all 可以同步验证多个表单。

  • 每个表单需要设置唯一的 ref,并通过 validate 方法进行验证。

  • 动态表单可以通过动态 ref 和 Promise.all 实现同步验证。

相关推荐
2501_944521594 小时前
Ramda 跨端三方库仓颉适配全流程
开发语言·javascript·flutter·php
0+1114 小时前
Linux --从 poll 到 epoll多路转接
linux·服务器·1024程序员节
青瓦梦滋4 小时前
WebSocket协议
linux·服务器·网络·c++·websocket·网络协议·http
桌面运维家5 小时前
旧电脑跑不动课程软件,VDI云桌面怎样接着用?
运维·服务器·虚拟化·pve·vdi·云桌面
zhang133830890755 小时前
传统机械三杯式风速传感器易磨损冻堵?CG-88金属超声波风速风向传感器给出免运维方案
运维·服务器·网络·人工智能·自动化
知已难寻5 小时前
第 2 篇 · 云的地基:服务器、存储、网络三大基础设施
运维·服务器·网络·云原生·云计算·负载均衡·1024程序员节
Ken_11155 小时前
小体积附件下载正常,大附件下载异常
javascript
变与不变8066 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半6 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck6 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法