You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt3中Vue Prime表单结合VeeValidate与Yup实现验证方案问询

问题:Nuxt3中结合Vue Prime组件实现VeeValidate表单验证

在Nuxt3项目中使用Vue Prime表单组件时,无法使用VeeValidate自带的Field组件,按官方文档操作无法实现验证功能。需要实现提交时验证和**实时验证(输入框失焦时显示错误信息)**的需求。

以下是原代码:

<template>
  <VForm @submit="handleAddUser" v-slot="{ values }">
    <FormItem :show-separator="false">
      <NuntioColorPicker @active-color="setUserColor" />
    </FormItem>
    <FormItem :show-separator="false" label="Display name">
      <InputText name="displayName" v-model="user.displayName" type="text" placeholder="Display name" />
      {{ errors.displayName }}
    </FormItem>
    <FormItem :show-separator="false" label="First name">
      <InputText v-model="user.firstName" type="text" placeholder="First name" />
    </FormItem>
    <FormItem :show-separator="false" label="Last name">
      <InputText v-model="user.lastName" type="text" placeholder="Last name" />
    </FormItem>
    <FormItem :show-separator="false" label="Email">
      <InputText v-model="user.email" type="text" placeholder="Email" />
    </FormItem>
    <FormItem :show-separator="false" label="Phone">
      <InputText v-model="user.phone" type="text" placeholder="Phone" />
    </FormItem>
    <FormItem :show-separator="false" label="Password">
      <InputText v-model="user.password" type="text" placeholder="Password" />
    </FormItem>
    <pre>{{ values }}</pre>
    <ModalActions>
      <NuntioButton ghost>Cancel</NuntioButton>
      <NuntioButton type="primary" @click="handleAddUser">Add user</NuntioButton>
      <button type="submit" @click="handleAddUser">SUbmit</button>
    </ModalActions>
  </VForm>
</template>

<script setup lang="ts">
import FormItem from '~/components/atoms/FormItem/FormItem.vue';
import NuntioColorPicker from '~/components/molecules/NuntioColorPicker.vue';
import InputText from 'primevue/inputtext';
import ModalActions from '~/components/organisms/Modal/ModalActions.vue';
import NuntioButton from '~/components/atoms/Button/NuntioButton.vue';
import { useForm, Form as VForm } from 'vee-validate';
import * as yup from 'yup';

//TODO: Typings
const user = reactive({
  color: undefined,
  displayName: undefined,
  firstName: undefined,
  lastName: undefined,
  email: undefined,
  password: undefined,
  phone: undefined
});

const userSchema = yup
  .object({
    displayName: yup.string().required(),
    firstName: yup.string().required(),
    lastName: yup.string().required(),
    email: yup.string().email().required(),
    password: yup.string().required().min(6),
    phone: yup.string().required()
  })
  .required();

const { validate, errors } = useForm({
  validationSchema: userSchema,
  initialValues: user
});

const setUserColor = (color: string) => {
  user.color = color;
};

const handleAddUser = (values) => {
  console.log('values', values);
  console.log('errors', errors.value);
};
</script>

<style scoped lang="scss"></style>

解决方案

关键修改点

  1. 利用VeeValidate提供的handleSubmit处理提交逻辑,自动触发全表单验证
  2. 给每个Vue Prime输入组件添加name属性和blur事件,实现失焦实时验证
  3. 绑定VeeValidate的values作为表单数据源,确保验证状态同步

修改后的完整代码

<template>
  <VForm v-slot="{ values }">
    <FormItem :show-separator="false">
      <NuntioColorPicker @active-color="setUserColor" />
    </FormItem>
    <FormItem :show-separator="false" label="Display name">
      <InputText 
        name="displayName" 
        v-model="values.displayName" 
        type="text" 
        placeholder="Display name"
        @blur="validateField('displayName')"
      />
      <span class="text-red-500">{{ errors.displayName }}</span>
    </FormItem>
    <FormItem :show-separator="false" label="First name">
      <InputText 
        name="firstName"
        v-model="values.firstName" 
        type="text" 
        placeholder="First name"
        @blur="validateField('firstName')"
      />
      <span class="text-red-500">{{ errors.firstName }}</span>
    </FormItem>
    <FormItem :show-separator="false" label="Last name">
      <InputText 
        name="lastName"
        v-model="values.lastName" 
        type="text" 
        placeholder="Last name"
        @blur="validateField('lastName')"
      />
      <span class="text-red-500">{{ errors.lastName }}</span>
    </FormItem>
    <FormItem :show-separator="false" label="Email">
      <InputText 
        name="email"
        v-model="values.email" 
        type="text" 
        placeholder="Email"
        @blur="validateField('email')"
      />
      <span class="text-red-500">{{ errors.email }}</span>
    </FormItem>
    <FormItem :show-separator="false" label="Phone">
      <InputText 
        name="phone"
        v-model="values.phone" 
        type="text" 
        placeholder="Phone"
        @blur="validateField('phone')"
      />
      <span class="text-red-500">{{ errors.phone }}</span>
    </FormItem>
    <FormItem :show-separator="false" label="Password">
      <InputText 
        name="password"
        v-model="values.password" 
        type="password" 
        placeholder="Password"
        @blur="validateField('password')"
      />
      <span class="text-red-500">{{ errors.password }}</span>
    </FormItem>
    <pre>{{ values }}</pre>
    <ModalActions>
      <NuntioButton ghost>Cancel</NuntioButton>
      <NuntioButton type="primary" @click="handleSubmit(handleAddUser)">Add user</NuntioButton>
      <button type="submit" @click="handleSubmit(handleAddUser)">Submit</button>
    </ModalActions>
  </VForm>
</template>

<script setup lang="ts">
import FormItem from '~/components/atoms/FormItem/FormItem.vue';
import NuntioColorPicker from '~/components/molecules/NuntioColorPicker.vue';
import InputText from 'primevue/inputtext';
import ModalActions from '~/components/organisms/Modal/ModalActions.vue';
import NuntioButton from '~/components/atoms/Button/NuntioButton.vue';
import { useForm, Form as VForm } from 'vee-validate';
import * as yup from 'yup';
import { watch } from 'vue';

const user = reactive({
  color: undefined,
  displayName: undefined,
  firstName: undefined,
  lastName: undefined,
  email: undefined,
  password: undefined,
  phone: undefined
});

const userSchema = yup
  .object({
    displayName: yup.string().required('Display name is required'),
    firstName: yup.string().required('First name is required'),
    lastName: yup.string().required('Last name is required'),
    email: yup.string().email('Invalid email format').required('Email is required'),
    password: yup.string().required('Password is required').min(6, 'Password must be at least 6 characters'),
    phone: yup.string().required('Phone is required')
  })
  .required();

const { handleSubmit, errors, validateField, values } = useForm({
  validationSchema: userSchema,
  initialValues: user
});

// 同步验证后的值到user对象
watch(values, (newValues) => {
  Object.assign(user, newValues);
}, { deep: true });

const setUserColor = (color: string) => {
  user.color = color;
};

const handleAddUser = (validatedValues) => {
  // 验证通过后执行业务逻辑
  console.log('Validated values:', validatedValues);
  console.log('User data:', user);
};
</script>

<style scoped lang="scss"></style>

功能说明

  • 实时验证:通过@blur="validateField('字段名')"在输入框失焦时触发单个字段的验证,即时显示错误提示
  • 提交验证:使用handleSubmit包裹提交方法,只有全表单验证通过后才会执行后续逻辑,避免无效提交
  • 状态同步:通过watch监听VeeValidate的values,同步到自定义的user对象,确保业务数据和表单状态一致

内容的提问来源于stack exchange,提问作者envy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:52:55