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

相关推荐
傻小胖1 分钟前
react的statehook useState Hook详细使用
前端·javascript·react.js
).(19 分钟前
el-table横向滚动条,滚动后消失
前端·css·css3
微臣酒驾来迟26 分钟前
el-descriptions-item使用span占行不生效
前端·javascript·vue.js
明月看潮生1 小时前
青少年编程与数学 02-006 前端开发框架VUE 22课题、状态管理
前端·javascript·vue.js·青少年编程·编程与数学
禾小毅1 小时前
vue 实现打包并同时上传至服务器端
前端·vue.js
Front_Yue1 小时前
Vue虚拟DOM:如何提高前端开发效率
前端·javascript·vue.js
Super毛毛穗1 小时前
Vue3学习总结
javascript·vue.js·学习
迃幵chen1 小时前
高可用虚拟IP-keepalived
linux·服务器·tcp/ip
林涧泣1 小时前
【Uniapp-Vue3】组合式API中的组件的生命周期函数(钩子函数)
前端·javascript·uni-app
疯狂的沙粒2 小时前
对受控组件和非受控组件的理解?应用场景?
前端·javascript·react.js·前端框架