简介
vue-uform 是一个面向组件、无内置样式的 Vue 3 表单处理与验证库。
设计目标为:
- 组件优先:表单、字段、提交按钮都是 Vue 组件,使用模板即可声明式构建表单。
- 无样式:不强制任何样式,完全交给用户或 UI 框架。
- 灵活的布局:可以为单个字段自定义结构,也可以为整个表单统一应用布局(scheme)。
- 内置与自定义验证:提供常用规则,并允许用户注册自定义规则(支持带参数)。
- f-model:配套小型 Vite 插件提供 f-model 语法糖,减少 :value + @input 的重复编写。
安装
pnpm install vue-uform
pnpm install @vue-uform/vite-plugin -D
在 vite.config.ts 中添加插件:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uForm from '@vue-uform/vite-plugin'
export default defineConfig({
plugins: [vue(), uForm()],
})
在 main.ts 中注册 Vue 插件:
import { createApp } from 'vue'
import App from './App.vue'
import { plugin as uformPlugin } from 'vue-uform'
createApp(App).use(uformPlugin, {}).mount('#app')
快速上手
最简示例:
<script setup>
const formValues = { username: '', password: '' }
function doLogin(data) {
console.log('Form submit:', data)
}
</script>
<template>
<u-form :values="formValues" @submit="doLogin">
<u-field name="username" label="Username" validation="required" v-slot="{ value, update }">
<input f-model />
</u-field>
<u-field name="password" label="Password" validation="required|min:6" v-slot="{ value, update }">
<input type="password" f-model />
</u-field>
<u-submit>Login</u-submit>
</u-form>
</template>
注:f-model 是通过 @vue-uform/vite-plugin 提供的语法糖,会被编译为等价的 :value 与事件监听。
内置验证规则
你可以在 的 validation 属性中直接使用这些规则,多个规则用 | 分隔,参数用 : 传入,多个参数用逗号 , 分隔。例如:validation="required|alpha|min:3|max:12"。
自定义验证规则(带参数)示例
下面是一个 min_words 的示例,检查输入文本至少包含指定数量的单词。此规则会接收来自 validation="min_words:5" 的参数 5。
<script setup lang="ts">
import { FieldNode } from "vue-uform"
// Custom rule: min_words
function minWords(node: FieldNode, min: number): boolean | string {
const value = String(node.value.value || "").trim()
if (!value) {
return `Please enter at least ${min} words.`
}
const wordCount = value.split(/\s+/).length
return wordCount >= min || `Please enter at least ${min} words.`
}
</script>
<template>
<u-form>
<u-field
name="bio"
label="Short Bio"
validation="min_words:5"
:rules="{ min_words: minWords }"
v-slot="{ value, update }"
>
<textarea f-model></textarea>
</u-field>
<u-submit>Submit</u-submit>
</u-form>
</template>
说明:
- :rules 对象用于向 注册自定义函数(键名与 validation 中的规则名一致)。
- 规则函数第一个参数是 FieldNode,可以通过 node.value.value 访问当前值;随后的参数对应 validation 中传入的参数。
f-model 与 vite 插件说明
f-model 是一个语法糖,由 @vue-uform/vite-plugin 在编译阶段将简写转换为标准绑定。常见转换示例:
- 普通输入:
<input f-model />
→ 编译为:
<input :value="value" @input="$event => update($event.target.value)" />
HTML 结构 / 布局可以自定义
vue-uform 的一大卖点是 完全可定制的字段结构。你可以:
-
在单个 中通过 custom + slot 自定义 HTML;
-
通过 scheme(传入一个 render function)为整个表单统一应用一种字段结构;
-
用 CSS / 自定义组件将字段统一样式化(例如将 label 放在左边、错误信息下方显示等)。
下面详细说明每种方式并给出示例。
方式一:使用
slot
自定义单字段结构
在 使用 v-slot 并传入 custom(或直接自定义 slot 内容)即可:
<template>
<u-form>
<u-field name="username" v-slot="{ value, update, messages, label, help }" custom>
<div class="my-field">
<label class="my-label">{{ label }}</label>
<div class="my-input-wrap">
<input f-model />
</div>
<div class="my-help">{{ help }}</div>
<ul class="my-errors">
<li v-for="err in messages" :key="err">{{ err }}</li>
</ul>
</div>
</u-field>
<u-submit>Submit</u-submit>
</u-form>
</template>
说明:
- v-slot 中通常会暴露 value, update, messages, label, help 等属性(具体字段名以库的实现为准)。
- custom 属性(或某个布尔 prop)用于告诉组件你要完全接管渲染(避免内部重复渲染默认结构)。
方式二:通过 scheme(render function)为所有字段统一应用结构
当你想让表单中 所有 字段共享一个统一结构(同样样式、相同 DOM 布局)时,可以在 <u-form> 上传入 scheme。scheme 是一个接收参数并返回 h(...) 的函数(render function)。
示例(TypeScript):
<script setup lang="ts">
import { h } from 'vue'
import { SchemeArg } from 'vue-uform' // 假设库导出了类型
const myScheme = (arg: SchemeArg) => {
// arg.slot() 是渲染字段 input 部分的函数
// arg.label / arg.help / arg.errors 是可用的属性
return h('div', { class: 'scheme-field' }, [
h('label', { class: 'scheme-label' }, arg.label),
h('div', { class: 'scheme-input' }, [arg.slot()]),
arg.help ? h('div', { class: 'scheme-help' }, arg.help) : null,
arg.messages && arg.messages.length
? h('ul', { class: 'scheme-errors' }, arg.messages.map((e: string) => h('li', e)))
: null,
])
}
</script>
<template>
<u-form :scheme="myScheme" :values="{ username: '' }">
<u-field name="username" label="Username" validation="required">
<input f-model />
</u-field>
<u-submit>Save</u-submit>
</u-form>
</template>
说明:
- arg.slot() 用来插入 field 内部的 input/textarea/组件部分(由你在 的 slot 提供)。
- scheme 统一了 DOM 结构与样式类,适合全局风格一致的需求。
- 使用 h 可以自由组合任意 DOM 与 Vue 组件。
联系我们 / 贡献
- GitHub 仓库:github.com/tu6ge/vue-u…
- StackBlitz: stackblitz.com/~/github.co…
- 欢迎提交 issue、PR 或建议.