)
UI组件前端【免费下载链接】shadcn-vueVue port of shadcn-ui项目地址https://gitcode.com/gh_mirrors/sh/shadcn-vue点击查看免费下载在 shadcn-vue 的开源仓库中deprecated/www/src/content/examples/forms/notifications.md是一个典型的示例页面入口它以极简的 Markdown 挂载一个完整的 Vue 示例组件向开发者演示如何在 shadcn-vue 生态中搭建一个真实可用的通知设置表单。本文以该文档为骨架结合仓库中示例组件与表单原语的源码实现完整拆解这个表单的 Schema 设计、vee-validate 校验管线、各类表单控件的绑定方式以及底层FormItem/FormControl的 accessibility 实现原理读完即可照搬到自己的设置页 / 偏好页开发中。一、示例入口从 Markdown 挂载 Vue 组件deprecated/www/src/content/examples/forms/notifications.md的全文非常简短只有三行有效代码script setup import NotificationsExample from /examples/forms/Notifications.vue /script NotificationsExample /这是 shadcn-vue 旧版文档站点位于deprecated/www目录的典型页面组织方式Markdown 内容页本身不做任何业务实现仅通过script setup引入并渲染对应的示例组件。从 import 路径可以推断别名指向src目录实际组件位于 deprecated/www/src/examples/forms/Notifications.vue。该组件是一个极薄的组合层将布局与表单解耦script setup langts import NotificationsForm from ./components/NotificationsForm.vue import FormsLayout from ./layouts/FormsLayout.vue /script template FormsLayout NotificationsForm / /FormsLayout /template也就是说这条页面渲染链路是notifications.md挂载点→Notifications.vue组合布局与表单→FormsLayout.vue页面骨架→NotificationsForm.vue表单本体文章的核心技术内容全部集中在 NotificationsForm.vue下面逐层展开。二、页面骨架FormsLayout 与侧边栏导航FormsLayout.vue 提供了设置中心风格的页面骨架包含页头、分割线与侧边栏 内容区的双栏布局template div classmd:hidden VPImage altForms width1280 height1214 classblock :image{ dark: /examples/forms-dark.png, light: /examples/forms-light.png, } / /div div classhidden space-y-6 p-10 pb-16 md:block div classspace-y-0.5 h2 classtext-2xl font-bold tracking-tightSettings/h2 p classtext-muted-foregroundManage your account settings and set e-mail preferences./p /div Separator classmy-6 / div classflex flex-col space-y-8 lg:flex-row lg:space-x-12 lg:space-y-0 aside class-mx-4 lg:w-1/5 SidebarNav / /aside div classflex-1 lg:max-w-2xl div classspace-y-6 slot / /div /div /div /div /template这里有两个值得注意的细节移动端回退在md断点以下直接渲染一张截图forms-dark.png/forms-light.png桌面端才展示真实交互表单——这是旧文档站对响应式预览的取舍插槽设计内容区通过slot /承接子页面因此Notifications、Account、Appearance等设置子页共享同一套骨架。侧边栏由 SidebarNav.vue 渲染它维护了五个设置子页的路由表const sidebarNavItems: Item[] [ { title: Profile, href: /examples/forms }, { title: Account, href: /examples/forms/account }, { title: Appearance, href: /examples/forms/appearance }, { title: Notifications, href: /examples/forms/notifications }, { title: Display, href: /examples/forms/display }, ]导航项使用Button的asa属性渲染为链接并通过$route.path \${item.href}.html判断当前激活态旧文档站基于 VitePress产物路径带.html后缀命中时追加bg-muted hover:bg-muted 样式。三、数据模型Zod Schema toTypedSchema通知表单的核心是 NotificationsForm.vue 中定义的类型安全 Schema。它使用vee-validate/zod的toTypedSchema把 Zod Schema 转换为 vee-validate 可消费的校验规则const notificationsFormSchema toTypedSchema(z.object({ type: z.enum([all, mentions, none], { required_error: You need to select a notification type., }), mobile: z.boolean().default(false).optional(), communication_emails: z.boolean().default(false).optional(), social_emails: z.boolean().default(false).optional(), marketing_emails: z.boolean().default(false).optional(), security_emails: z.boolean(), }))逐字段解读字段类型定义默认值界面控件typez.enum([all, mentions, none])带required_error无必填RadioGroup 单选mobilez.boolean().default(false).optional()falseCheckboxcommunication_emailsz.boolean().default(false).optional()falseSwitchmarketing_emailsz.boolean().default(false).optional()falseSwitchsocial_emailsz.boolean().default(false).optional()trueSwitchsecurity_emailsz.boolean()trueSwitch语义说明type是唯一带校验错误提示的字段——如果用户提交时未选择任何通知类型Zod 会抛出required_error中的文案最终由FormMessage渲染布尔字段统一声明为optional()使得未勾选与显式 false在类型层面都可接受避免表单在空值状态下触发多余的必填校验.default(false)与useForm的initialValues双轨配合见下一节。四、表单初始化useForm 与 initialValues接下来通过 vee-validate 的useForm建立表单实例注入校验 Schema 并提供首屏默认值const { handleSubmit } useForm({ validationSchema: notificationsFormSchema, initialValues: { communication_emails: false, marketing_emails: false, social_emails: true, security_emails: true, }, })这里体现了两个关键点validationSchema传入toTypedSchema的产物vee-validate 会在每次字段变更与提交时执行 Zod 校验并把错误映射回对应字段initialValues与 Schema 默认值的关系type与mobile未出现在initialValues中——type依赖required_error强制用户选择mobile依赖 Schema 中的.default(false)兜底。而三个邮箱开关的初始状态在initialValues中显式给出其中social_emails和security_emails默认开启communication_emails与marketing_emails默认关闭模拟了真实产品的合理默认。五、提交处理handleSubmit toast 反馈表单提交经由handleSubmit包裹成功回调中把最终值序列化并通过 toast 呈现const onSubmit handleSubmit((values) { toast({ title: You submitted the following values:, description: h(pre, { class: mt-2 w-[340px] rounded-md bg-slate-950 p-4 }, h(code, { class: text-white }, JSON.stringify(values, null, 2))), }) })细节说明这里用h()Vue 的渲染函数在 toast 描述中构造一个等宽字体的precode块格式化输出JSON.stringify(values, null, 2)便于开发者直观核对提交数据toast来自/registry/new-york/ui/toast即 shadcn-vue 的 new-york 风格 toast 组件提交按钮为typesubmit触发表单的原生 submit 事件模板中通过submitonSubmit绑定。六、通知类型的单选组FormField RadioGroup通知类型是表单唯一的必填字段采用卡片式单选组。shadcn-vue 的表单字段统一由FormField驱动其type属性决定字段的数据类型与插槽签名FormField v-slot{ componentField } typeradio nametype FormItem classspace-y-3 FormLabelNotify me about.../FormLabel FormControl RadioGroup classflex flex-col space-y-1 v-bindcomponentField FormItem classflex items-center space-x-3 space-y-0 FormControl RadioGroupItem valueall / /FormControl FormLabel classfont-normalAll new messages/FormLabel /FormItem FormItem classflex items-center space-x-3 space-y-0 FormControl RadioGroupItem valuementions / /FormControl FormLabel classfont-normalDirect messages and mentions/FormLabel /FormItem FormItem classflex items-center space-x-3 space-y-0 FormControl RadioGroupItem valuenone / /FormControl FormLabel classfont-normalNothing/FormLabel /FormItem /RadioGroup /FormControl FormMessage / /FormItem /FormField要点拆解v-slot{ componentField }拿到 vee-validate 为该字段生成的属性集合通过v-bindcomponentField展开到RadioGroup上实现受控绑定每个选项复用FormItem FormControl RadioGroupItem FormLabel的组合形成标签 圆点的水平布局内层FormLabel追加font-normal以区别于外层组标题FormMessage放在FormItem末尾required_error未触发时渲染为空触发时自动显示校验文案。七、邮箱通知开关组FormField Switch四个邮箱开关的结构完全一致都是说明文字居左、Switch 居右的边框卡片。以communication_emails为例FormField v-slot{ handleChange, value } typecheckbox namecommunication_emails FormItem classflex flex-row items-center justify-between rounded-lg border p-4 div classspace-y-0.5 FormLabel classtext-baseCommunication emails/FormLabel FormDescriptionReceive emails about your account activity./FormDescription /div FormControl Switch :model-valuevalue update:model-valuehandleChange / /FormControl /FormItem /FormField与单选组不同Switch 场景下FormField插槽解构的是{ handleChange, value }value当前布尔值通过:model-value传给SwitchhandleChange字段变更回调绑定update:model-value把 Switch 的新值写回表单状态。其余三个开关只是文案与字段名不同规格完全相同FormField v-slot{ handleChange, value } typecheckbox namemarketing_emails !-- Marketing emails / Receive emails about new products, features, and more. -- /FormField FormField v-slot{ handleChange, value } typecheckbox namesocial_emails !-- Social emails / Receive emails for friend requests, follows, and more. -- /FormField FormField v-slot{ handleChange, value } typecheckbox namesecurity_emails !-- Security emails / Receive emails about your account activity and security. -- /FormField八、移动端设置FormField Checkbox最后一项是移动端差异化设置使用 Checkbox并带有一个指向/examples/forms的说明链接FormField v-slot{ handleChange, value } typecheckbox namemobile FormItem classflex flex-row items-start space-x-3 space-y-0 FormControl Checkbox :model-valuevalue update:model-valuehandleChange / /FormControl div classspace-y-1 leading-none FormLabelUse different settings for my mobile devices/FormLabel FormDescription You can manage your mobile notifications in the a href/examples/formsmobile settings/a page. /FormDescription /div /FormItem /FormField这里展示了一个常见模式复选框与说明文本左右并排说明中嵌入超链接引导用户跳转相关页面。布局上使用items-start让复选框与多行说明顶部对齐。九、表单原语的源码实现可访问性从哪来以上所有字段都建立在 shadcn-vue 的Form*原语之上。这些原语在注册表中统一导出见 deprecated/www/src/registry/new-york/ui/form/index.tsexport { default as FormControl } from ./FormControl.vue export { default as FormDescription } from ./FormDescription.vue export { default as FormItem } from ./FormItem.vue export { default as FormLabel } from ./FormLabel.vue export { default as FormMessage } from ./FormMessage.vue export { FORM_ITEM_INJECTION_KEY } from ./injectionKeys export { Form, Field as FormField, FieldArray as FormFieldArray } from vee-validate注意最后一行FormField以及Form、FormFieldArray并非仓库自研组件而是直接转发自vee-validate的Field这也是示例中FormField能直接支持v-slot{ handleChange, value, componentField }的原因。字段关联 ID 的传递FormItem通过provide(FORM_ITEM_INJECTION_KEY, id)向子组件注入唯一 ID见 deprecated/www/src/registry/default/ui/form/FormItem.vueFormControl、FormLabel、FormDescription、FormMessage再从注入上下文中取出formItemId、formDescriptionId、formMessageId与error状态。ARIA 语义的落地以 new-york 风格的 FormControl.vue 为例它基于 reka-ui 的Slot组件把语义属性注入到控件根元素上const { error, formItemId, formDescriptionId, formMessageId } useFormField() Slot :idformItemId :aria-describedby!error ? ${formDescriptionId} : ${formDescriptionId} ${formMessageId} :aria-invalid!!error slot / /Slot这保证了每个控件都有与FormLabel匹配的idfor/id关联无错误时aria-describedby只指向描述文本有错误时同时拼接描述与错误消息 ID屏幕阅读器能依次读出描述 错误错误存在时aria-invalidtrue被自动置上。也就是说示例里一行FormMessage或FormControl其背后的无障碍关联是注册表组件层自动完成的——这正是 shadcn-vue 表单原语的价值所在。同一套原语在default与new-york两套风格注册表中均有实现default 风格导出见 deprecated/www/src/registry/default/ui/form/index.ts示例表单混用了两套Form*原语来自 default 风格Button、Checkbox、RadioGroup、Switch、Separator、toast来自 new-york 风格。十、从示例到实战可复用的模式总结回顾整个示例可以提炼出 shadcn-vue 设置页表单的通用套路页面层notifications.md或任意路由组件→ 布局组件 表单组件布局用slot /承接内容侧边栏用Button asa渲染导航数据层toTypedSchema(z.object({...}))定义类型安全的 Schemarequired_error负责必填文案.default()与initialValues配合设定初始状态绑定层单选用v-slot{ componentField }v-bind开关/复选用v-slot{ handleChange, value } 手动事件绑定呈现层FormItem / FormLabel / FormControl / FormDescription / FormMessage五件套统一排版与无障碍语义错误提示无需手写条件渲染反馈层handleSubmit成功回调中通过toast输出提交值便于联调。如果需要继续参考同系列的设置页实现仓库中还有Account、Appearance、Display、Profile四个等价示例入口分别位于deprecated/www/src/examples/forms/Account.vue 与 AccountForm.vuedeprecated/www/src/examples/forms/Appearance.vue 与 AppearanceForm.vuedeprecated/www/src/examples/forms/Display.vue 与 DisplayForm.vuedeprecated/www/src/examples/forms/Example.vue 与 ProfileForm.vue它们共享同一个FormsLayout与SidebarNav且都用vee-validate/zod驱动校验——看完本文的 Notifications 示例即可触类旁通地阅读其余表单。需要说明的是本示例位于仓库的deprecated/www旧版文档目录下属于历史文档站资产其组件代码与注册表实现仍完整保留在当前仓库中可作为学习与移植的参考。赞分享UI组件前端【免费下载链接】shadcn-vueVue port of shadcn-ui项目地址https://gitcode.com/gh_mirrors/sh/shadcn-vue点击查看免费下载相关推荐shadcn-vue 表单实战基于 vee-validate 与 Zod 构建 Display 侧边栏显示项开关表单shadcn vue 表单实战基于 vee validate 与 Zod 构建 Display 侧边栏显示项开关表单 本文围绕 shadcn vue 仓库中UI组件前端用vee-validate构建复杂表单多步表单向导与动态表单生成器实战用vee validate构建复杂表单多步表单向导与动态表单生成器实战 vee validate 是 Vue 官方生态中广受欢迎的表单验证库口号是 Pai前端UI组件vue-vben-admin 表单引擎迁移实战Zod 4 与 TanStack Form 完全替换 vee-validatevue vben admin 表单引擎迁移实战Zod 4 与 TanStack Form 完全替换 vee validate 本篇指南以 vue vben a前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考