Vee-validate结合Yup动态输入字段不验证且无错误提示问题
问题:VeeValidate + Yup 动态生成嵌套字段验证失效
这是此前相关问题的跟进提问,因需循环渲染字段,尝试动态配置VeeValidate与Yup,但复刻静态配置方式后,动态字段既不触发验证也不显示错误。
脚本代码
import { useForm } from 'vee-validate' import * as yup from 'yup' const { values, errors, defineComponentBinds, isSubmitting, setFieldValue, handleSubmit } = useForm({ validationSchema: yup.object({ moduleValidationInputs: yup.object(moduleValidationSchemes.value) }) }) const moduleValidationSchemes = ref({}) const moduleValidationInputs = ref({}) onMounted(() => { newModuleFields.value.map(nmf => { if (nmf.rules && nmf.rules.required) { moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).required() } else moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).nullable() moduleValidationInputs.value[nmf.uniqueName] = defineComponentBinds(`moduleValidationInputs.${nmf.uniqueName}`) }) })
模板代码
<div v-for="(requiredField, rfx) in requiredFields" :key="rfx" class="col-6"> <p>{{ errors }}</p> <span class="p-float-label"> <InputText v-bind="moduleValidationInputs[requiredField.uniqueName]" class="w-full border-left-3 border-red-600" /> <label>{{ requiredField.label }}</label> </span> </div>
验证对比
将验证Schema替换为静态配置时,验证正常生效:
moduleValidationInputs: yup.object({ lead_company: yup.string().label('Company').required() })
疑问:是否VeeValidate的useForm不支持动态生成Yup对象作为validationSchema?我的操作哪里有误?
解决方案
问题核心是**useForm初始化时,moduleValidationSchemes.value还是空对象**,后续修改ref值不会触发VeeValidate自动更新验证规则——因为validationSchema在useForm初始化时就已固化,不会响应ref的变化。
下面提供两种可行的解决方式:
方式一:延迟初始化useForm
等字段配置就绪后再调用useForm,确保初始化时验证规则已完整:
import { useForm } from 'vee-validate' import * as yup from 'yup' const moduleValidationSchemes = ref({}) const moduleValidationInputs = ref({}) let formContext = null onMounted(() => { // 先构建完整的验证规则 newModuleFields.value.forEach(nmf => { if (nmf.rules?.required) { moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).required() } else { moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).nullable() } }) // 再初始化表单 formContext = useForm({ validationSchema: yup.object({ moduleValidationInputs: yup.object(moduleValidationSchemes.value) }) }) // 绑定字段 newModuleFields.value.forEach(nmf => { moduleValidationInputs.value[nmf.uniqueName] = formContext.defineComponentBinds(`moduleValidationInputs.${nmf.uniqueName}`) }) }) // 按需解构表单方法供外部使用 const { values, errors, isSubmitting, handleSubmit } = computed(() => formContext || {})
方式二:用setValidationSchema动态更新规则
利用useForm返回的setValidationSchema方法,在构建完规则后动态替换验证Schema:
import { useForm } from 'vee-validate' import * as yup from 'yup' const { values, errors, defineComponentBinds, isSubmitting, setFieldValue, handleSubmit, setValidationSchema // 新增该方法 } = useForm({ // 先初始化空的基础Schema validationSchema: yup.object({ moduleValidationInputs: yup.object({}) }) }) const moduleValidationSchemes = ref({}) const moduleValidationInputs = ref({}) onMounted(() => { // 构建验证规则 newModuleFields.value.forEach(nmf => { if (nmf.rules?.required) { moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).required() } else { moduleValidationSchemes.value[nmf.uniqueName] = yup.string().label(nmf.label).nullable() } moduleValidationInputs.value[nmf.uniqueName] = defineComponentBinds(`moduleValidationInputs.${nmf.uniqueName}`) }) // 动态更新验证规则 setValidationSchema(yup.object({ moduleValidationInputs: yup.object(moduleValidationSchemes.value) })) })
额外提示
- 遍历数组执行副作用操作时,用
forEach比map更语义化(map本意是返回新数组,而非执行副作用)。 - 如果
newModuleFields是异步获取的,要等数据返回后再执行规则构建和字段绑定逻辑,比如放在watch里监听newModuleFields的变化。
内容的提问来源于stack exchange,提问作者Lekz Flores
相关产品推荐
相关产品推荐

