如何在父子关系中使用 vee-validate

How to use vee-validate in a parent-child relationship

我有几个组件需要验证。问题是输入在子组件中,而提交按钮在父组件中,就像这样

ParentComponent.js

<ValidationObserver v-slot="{ passes }"> 
     <form @submit.prevent="passes(someSubmitFunction)">
         <ChildComponent />
     </form>
</ValidationObserver>

ChildComponent.js

     <ValidationProvider rules="required" v-slot="{ errors }" name="vendorName">
         <el-input />
      </ValidationProvider>

我做错了什么?

您可以在子组件上使用 ref,然后在调用 someSubmitFunction

时尝试对该 ref 进行验证

像这样:

  const isValid = await this.$refs.childref.validate()

幸运的是,有一种模式可以在父组件和子组件之间共享验证器范围!您可以 inject 验证器从父级到子级,以便它们使用相同的实例。这意味着您可以使用 this.$validator.validate()

验证来自父项的子项输入

文档: http://vee-validate.logaretm.com/v2/concepts/injections.html

您可以像这样在创建的钩子中通过父组件验证器覆盖 chid 组件验证器的实例。

created() {
 this.$validator = this.$parent.$validator
}

注意:如果你使用 mounted 它会起作用,因为在 DOM 渲染替换之前必须完成。

像我这样的人,以后和v4vee-validate一起来这里求教 Vue3 Composition API and Typescript,我想推荐这个答案。它的工作原理是将 useForm 中的每个 validate 方法添加到数组中,然后在表单提交时循环遍历数组以确保所有验证器异步传递。

formAggregator.ts

import { InjectionKey, provide, ref } from "vue";

type ValidatorMethodType = () => Promise<{ valid: boolean }>;

export const AddValidatorKey: InjectionKey<
  (validator: ValidatorMethodType) => void
> = Symbol("AddValidatorKey");

export function useValidationAggregator() {
  const validators = ref<ValidatorMethodType[]>([]);

  // used by components to add validators to the array
  const register = (validator: ValidatorMethodType) => {
    validators.value.push(validator);
  };

  // provide this aggregator to components
  provide(AddValidatorKey, register);

  // run all validators
  const validateAll = async () => {
    return Promise.all(validators.value.map((v) => v()));
  };

  return {
    validateAll,
    register,
  };
}

ParentComponent.vue

<template>
<form @submit.prevent="onSubmit">
    <ChildComponent />
   <button type="submit" :disabled="inSubmit">Submit</button>
</form>
</template>
<script setup>
import useValidationAggregator from "./formAggregator.ts"
const { validateAll } = useValidationAggregator();
// note: you can use register() to also add validator from the parent component

const inSubmit = ref(false);
const onSubmit = async () => {
   try {
      inSubmit.value = true;

      // run all form validators
      const results = await validateAll();

      // ensure all are valid
      if (results.some((r) => !r.valid)) {
         return;
      }

      // todo: post form or whatever you need after validation passes
   } finally {
      inSubmit.value = false;
   }
}
</script>

ChildComponent.vue

<template>
   <!-- some validated fields -->
</template>
<script setup>
import { AddValidatorKey } from "./formAggregator.ts"

const { validate } = useForm({ ... setup validated fields ... });

// add this component's validator to the aggregator
const addValidator = inject(AddValidatorKey, () => {
  throw new Error("No aggregator provided for inject");
});
addValidator(validate);
</script>

当 运行 验证父 ValidationObserver 时,它也会验证子 ValidationObserver。
如果您只需要验证父 ValidationObserver,您可以为子观察者使用“禁用”道具。
https://vee-validate.logaretm.com/v3/api/validation-observer.html#props

<ValidationObserver ref="parent">
  <ValidationObserver ref="child" :disabled="true">
    <ValidationProvider rules="required">
      <!-- This child observer will not be validated with parent validation -->
    </ValidationProvider>
  </ValidationObserver>
</ValidationObserver>