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 元素绑定到表单 API。 此外,通过 validateOn*、initialValue、resolver 和 name 等属性,可以直接从该组件控制行为。
import { FormField } from '@primevue/forms';
尽管 PrimeVue 组件内置了对表单 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>
表单 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>
本节演示如何使用自定义表单组件创建动态表单。 它展示了一个示例,其中表单字段是根据提供的配置动态生成的,从而允许灵活的表单结构。 此示例中显示的名为 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>
表单不需要任何角色和属性。
组件不包含任何交互式元素。