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

在 Vue 和 Element UI 中,如果多个表单使用相同的 refrules,可能会导致表单验证规则不生效。这是因为 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(如 form1Refform2Ref)。

  • 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(如 formRef0formRef1)。

  • 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(如 form1Refform2Ref)。

动态表单的同步验证

如果表单是动态生成的(例如通过 v-for 循环),可以使用动态 refPromise.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 方法进行验证。

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

相关推荐
Allen Bright3 分钟前
【CSS-5】掌握CSS文本样式:从基础到高级技巧
前端·css
贩卖纯净水.11 分钟前
Webpack常见的插件和模式
前端·webpack·node.js
brzhang19 分钟前
Flutter 调用原生代码,看这篇就够了:从零教你搭起通信的桥
前端·后端·架构
程序员小张丶19 分钟前
React Native在HarmonyOS 5.0阅读类应用开发中的实践
javascript·react native·react.js·阅读·harmonyos5.0
EndingCoder19 分钟前
React Native 是什么?为什么学它?
javascript·react native·react.js
袁煦丞20 分钟前
知识管理的六边形战士Trilium Notes:cpolar内网穿透实验室第520个成功挑战
前端·程序员·远程工作
失败又激情的man29 分钟前
python爬虫之数据存储
前端·数据库·python
互联网搬砖老肖29 分钟前
Web 架构之 API 安全防护:防刷、防爬、防泄漏
前端·安全·架构
摸鱼仙人~40 分钟前
Redux Toolkit 快速入门指南:createSlice、configureStore、useSelector、useDispatch 全面解析
开发语言·javascript·ecmascript
小声读源码1 小时前
【技巧】dify前端源代码修改第一弹-增加tab页
前端·pnpm·next.js·dify