多个表单使用相同的 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 实现同步验证。

相关推荐
Bony-1 小时前
Go语言完全学习指南 - 从基础到精通------语言基础篇
服务器·开发语言·golang
阿巴~阿巴~2 小时前
线程安全单例模式与懒汉线程池的实现与优化
linux·服务器·单例模式·线程池·饿汉模式·懒汉模式·静态方法
大隐隐于野2 小时前
tcp 丢包分析
linux·服务器·网络
Broken Arrows2 小时前
在Linux系统中,top命令的显示参数详解
linux·运维·服务器
APIshop2 小时前
PHP:一种强大的服务器端脚本语言
服务器·php
漂流瓶jz3 小时前
Webpack中各种devtool配置的含义与SourceMap生成逻辑
前端·javascript·webpack
这是个栗子3 小时前
【问题解决】用pnpm创建的 Vue3项目找不到 .eslintrc.js文件 及 后续的eslint配置的解决办法
javascript·vue.js·pnpm·eslint
前端架构师-老李3 小时前
React 中 useCallback 的基本使用和原理解析
前端·react.js·前端框架
木易 士心4 小时前
CSS 中 `data-status` 的使用详解
前端·css
明月与玄武4 小时前
前端缓存战争:回车与刷新按钮的终极对决!
前端·缓存·回车 vs 点击刷新