PrimeVue 表单库提供全面的表单状态管理和内置的验证支持。
表单附加组件可在 npm 注册表中下载。
# Using npm
npm install @primevue/forms
# Using yarn
yarn add @primevue/forms
# Using pnpm
pnpm add @primevue/forms
表单组件负责管理表单状态,并且必须封装表单字段。
import { Form } from '@primevue/forms';
所有 PrimeVue 表单组件都设计为与表单库无缝集成。 不使用标准 v-model,而是使用 name 属性来链接跟踪值、错误和操作的状态对象。 表单组件提供了四个用于状态管理的关键属性。
属性 | 描述 |
---|---|
v-slot="$form" | 公开跟踪字段状态管理的主要 $form 对象。 |
initialValues | 指定用于初始化表单的默认值。 |
resolver | 验证处理程序,用于实现验证或绑定类似 Zod、Yup、Valibot 等的模式。 |
@submit | 表单提交时执行的事件处理程序。 |
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error?.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
$form 对象跟踪字段的状态管理。 每个字段都与 name 属性链接。 有关每个属性的详细信息,请查看 API 文档中的 FormFieldState 类型。
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid lg:grid-cols-2 gap-4 w-full">
<div class="flex flex-col justify-center items-center gap-4">
<InputText name="username" type="text" placeholder="Username" class="w-full sm:w-56" />
<Button type="submit" severity="secondary" label="Submit" class="w-full sm:w-56" />
</div>
<Fieldset legend="Form States" class="h-80 overflow-auto">
<pre class="whitespace-pre-wrap">{{ $form }}</pre>
</Fieldset>
</Form>
验证是通过 resolver 属性实现的。 自定义解析器负责处理验证并返回一个 errors 对象,其中键是表单字段名称,值是一个错误对象数据数组。 为了提高效率,我们建议使用模式验证库,而不是构建自己的自定义验证逻辑。 表单库为流行的选项提供了内置的解析器,包括 Zod、Yup、Joi、Valibot 和 Superstruct,可以从 @primevue/forms/resolvers 路径导入。
<Form v-slot="$form" :initialValues :resolver="resolver" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
表单组件支持灵活的验证触发器,允许在值更新、失去焦点事件、表单挂载或提交时进行验证。 这些行为可以在表单级别配置,也可以通过 formControl 属性的 validateOnValueUpdate、validateOnBlur、validateOnMount 和 validateOnSubmit 选项在特定字段上配置。
在此示例中,表单在表单级别禁用 validateOnValueUpdate 并启用 validateOnBlur,并在挂载时验证 firstName。 firstName 字段在本地覆盖表单级别的设置。
<Form v-slot="$form" :initialValues :resolver :validateOnValueUpdate="false" :validateOnBlur="true" :validateOnMount="['firstName']" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<InputText name="firstName" type="text" placeholder="First Name" fluid :formControl="{ validateOnValueUpdate: true }" />
<Message v-if="$form.firstName?.invalid" severity="error" size="small" variant="simple">{{ $form.firstName.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<InputText name="lastName" type="text" placeholder="Last Name" fluid />
<Message v-if="$form.lastName?.invalid" severity="error" size="small" variant="simple">{{ $form.lastName.error.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
FormField 是一个辅助组件,为输入元素提供验证和跟踪,提供更灵活的结构,将 PrimeVue、非 PrimeVue 组件或原生 HTML 元素绑定到 Form API。 此外,通过 validateOn*、initialValue、resolver 和 name 等属性,可以直接从该组件控制行为。
import { FormField } from '@primevue/forms';
虽然 PrimeVue 组件对 Form API 具有内置支持,但您可能仍然希望使用 FormField 包装的组件。 这是一种偏好问题,例如,如果您还对其他第三方组件、您自己的自定义组件和原生元素使用 FormField,那么为了保持一致性,这可能是一个选项。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" name="username" initialValue="" class="flex flex-col gap-1">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
Form API 并非严格绑定到 PrimeVue 组件,它提供了一种灵活的方式来管理任何原生 HTML 元素、您自己的自定义组件或第三方库的验证和状态。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" name="username" initialValue="" class="flex flex-col gap-1">
<input type="text" placeholder="Username" :class="[{ error: $field?.invalid }]" v-bind="$field.props" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="password" initialValue="PrimeVue" class="flex flex-col gap-1">
<input v-model="$field.value" type="password" placeholder="Password" :class="[{ error: $field?.invalid }]" @input="$field.onInput" @blur="$field.onBlur" @change="$field.onChange" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
每个 FormField 都可以有自己的专用解析器,允许您为各个字段定义自定义验证逻辑。 这种灵活性支持定制的验证规则,确保每个表单字段都满足特定条件。
<Form :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-80">
<FormField v-slot="$field" name="username" initialValue="" :resolver="zodUserNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="firstname" initialValue="" :resolver="yupFirstNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="First Name" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="lastname" initialValue="" :resolver="valibotLastNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="Last Name" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="password" initialValue="" :resolver="customPasswordResolver" class="flex flex-col gap-1">
<Password type="text" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="details" class="flex flex-col gap-1">
<Textarea placeholder="Details" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
它呈现为 HTML div 元素,但是可以使用 as 和 asChild 属性修改此行为,以呈现不同的 HTML 元素或传递自定义组件,从而在表单结构中提供更大的灵活性。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" as="section" name="username" initialValue="" class="flex flex-col gap-2">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" asChild name="password" initialValue="">
<section class="flex flex-col gap-2">
<Password type="text" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</section>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
submit 回调返回一个对象,该对象封装了表单的有效性、任何现有错误及其当前状态。 这可以访问表单值、验证状态和提交时存在的任何错误。 有关可用事件数据的更多信息,请查看 API 文档中的 FormSubmitEvent。
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<Password name="password" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$form.password?.invalid" severity="error" size="small" variant="simple">
<ul class="my-0 px-4 flex flex-col gap-1">
<li v-for="(error, index) of $form.password.errors" :key="index">{{ error.message }}</li>
</ul>
</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
本节演示如何使用自定义 Form 组件创建动态表单。 它展示了一个示例,其中表单字段是根据提供的配置动态生成的,从而允许灵活的表单结构。 此示例中显示的名为 Dynamic* 的组件不是内置的,仅用于示例目的。 第一个表单使用声明式方法,而第二个表单使用编程方法。 我们建议在 StackBlitz 中运行此示例以查看完整的实现。
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
表单不需要任何角色和属性。
组件不包含任何交互元素。