Form UI 组件
Form UI 组件是一个基于 Vue 3 的高度可定制化表单组件,提供了丰富的表单项和布局选项,支持表单验证、联动和动态渲染等功能。
安装
npm install @cimom/vben-core-ui-kit-form-ui
基本使用
<script setup lang="ts">
import { VbenForm } from '@cimom/vben-core-ui-kit-form-ui';
import { ref } from 'vue';
import { z } from 'zod';
const formData = ref({
username: '',
password: '',
});
const schema = [
{
fieldName: 'username',
label: '用户名',
component: 'VbenInput',
componentProps: {
placeholder: '请输入用户名',
},
rules: z.string().min(3, '用户名至少3个字符'),
required: true,
},
{
fieldName: 'password',
label: '密码',
component: 'VbenInputPassword',
componentProps: {
placeholder: '请输入密码',
},
rules: z.string().min(6, '密码至少6个字符'),
required: true,
},
];
const handleSubmit = (values) => {
console.log('表单提交:', values);
};
const handleReset = () => {
console.log('表单重置');
};
</script>
<template>
<VbenForm
v-model="formData"
:schema="schema"
:handle-submit="handleSubmit"
:handle-reset="handleReset"
/>
</template>
组件属性
VbenForm Props
属性名 | 类型 | 默认值 | 说明 |
---|
modelValue | Record<string, any> | {} | 表单数据对象 |
schema | FormSchema[] | [] | 表单配置模式 |
layout | 'horizontal' \| 'vertical' | 'horizontal' | 表单布局方式 |
collapsed | boolean | false | 是否折叠表单 |
collapsedRows | number | 1 | 折叠时显示的行数 |
showCollapseButton | boolean | false | 是否显示折叠按钮 |
showDefaultActions | boolean | true | 是否显示默认的操作按钮 |
submitButtonOptions | ActionButtonOptions | {} | 提交按钮配置 |
resetButtonOptions | ActionButtonOptions | {} | 重置按钮配置 |
actionWrapperClass | string | '' | 操作按钮容器的类名 |
wrapperClass | WrapperClassType | 'grid-cols-1' | 表单容器的类名 |
commonConfig | FormCommonConfig | {} | 公共配置 |
handleSubmit | HandleSubmitFn | undefined | 提交表单的处理函数 |
handleReset | HandleResetFn | undefined | 重置表单的处理函数 |
handleValuesChange | (values: Record<string, any>, fieldsChanged: string[]) => void | undefined | 表单值变化的处理函数 |
submitOnChange | boolean | false | 值变化时是否自动提交 |
submitOnEnter | boolean | false | 按回车键是否自动提交 |
FormSchema 配置项
属性名 | 类型 | 说明 |
---|
fieldName | string | 字段名称(必填) |
label | string \| (() => Component \| string) | 标签文本 |
component | Component \| string | 组件类型 |
componentProps | MaybeComponentProps \| ((value, actions) => MaybeComponentProps) | 组件属性 |
defaultValue | any | 默认值 |
rules | FormSchemaRuleType | 验证规则 |
required | boolean | 是否必填 |
help | string \| (() => Component \| string) | 帮助信息 |
description | string \| (() => Component \| string) | 描述信息 |
suffix | string \| (() => Component \| string) | 后缀内容 |
dependencies | FormItemDependencies | 依赖配置 |
renderComponentContent | RenderComponentContentType | 自定义渲染组件内容 |
FormCommonConfig 公共配置
属性名 | 类型 | 默认值 | 说明 |
---|
disabled | boolean | false | 是否禁用所有表单项 |
hideLabel | boolean | false | 是否隐藏所有表单项的标签 |
labelWidth | number | - | 标签宽度 |
labelClass | string | '' | 标签类名 |
controlClass | string | '' | 控件类名 |
formItemClass | string | '' | 表单项类名 |
colon | boolean | false | 是否在标签后显示冒号 |
hideRequiredMark | boolean | false | 是否隐藏必填标记 |
emptyStateValue | null \| undefined | undefined | 空状态值 |
表单项联动
可以通过 dependencies
属性设置表单项之间的联动关系:
<script setup>
const schema = [
{
fieldName: 'type',
label: '类型',
component: 'VbenSelect',
componentProps: {
options: [
{ label: '类型A', value: 'A' },
{ label: '类型B', value: 'B' },
],
},
},
{
fieldName: 'extraInfo',
label: '额外信息',
component: 'VbenInput',
dependencies: {
triggerFields: ['type'],
show: (values) => values.type === 'B',
required: (values) => values.type === 'B',
},
},
];
</script>
使用 API 方法
<script setup>
import { VbenForm, useVbenForm } from '@cimom/vben-core-ui-kit-form-ui';
import { ref } from 'vue';
const formRef = ref(null);
const { formApi } = useVbenForm(formRef);
// 使用表单API
const handleClick = () => {
// 获取表单值
const values = formApi.getValues();
// 设置表单值
formApi.setValues({ username: 'admin' });
// 验证表单
formApi.validate().then((result) => {
if (result.valid) {
console.log('表单验证通过');
}
});
// 重置表单
formApi.reset();
};
</script>
<template>
<VbenForm ref="formRef" :schema="schema" />
<button @click="handleClick">操作表单</button>
</template>
可用的表单API方法
方法名 | 参数 | 返回值 | 说明 |
---|
getValues | - | Record<string, any> | 获取表单所有值 |
getValue | (name: string) | any | 获取指定字段的值 |
setValues | (values: Record<string, any>) | void | 设置表单多个值 |
setValue | (name: string, value: any) | void | 设置指定字段的值 |
validate | (names?: string[]) | Promise<{ valid: boolean, errors: Record<string, string> }> | 验证表单 |
reset | (names?: string[]) | void | 重置表单 |
setFieldError | (name: string, error: string) | void | 设置字段错误信息 |
clearErrors | (names?: string[]) | void | 清除错误信息 |
setFieldTouched | (name: string, isTouched: boolean) | void | 设置字段触摸状态 |
setFieldDisabled | (name: string, disabled: boolean) | void | 设置字段禁用状态 |
示例
基础表单示例
<template>
<div class="p-4">
<h2 class="mb-4 text-lg font-bold">基础表单</h2>
<VbenForm
v-model="formData"
:schema="schema"
:handle-submit="handleSubmit"
:handle-reset="handleReset"
/>
</div>
</template>
<script setup lang="ts">
import { VbenForm } from '@cimom/vben-core-ui-kit-form-ui';
import { ref } from 'vue';
import { z } from 'zod';
const formData = ref({
username: '',
password: '',
remember: false,
});
const schema = [
{
fieldName: 'username',
label: '用户名',
component: 'VbenInput',
componentProps: {
placeholder: '请输入用户名',
},
rules: z.string().min(3, '用户名至少3个字符'),
required: true,
},
{
fieldName: 'password',
label: '密码',
component: 'VbenInputPassword',
componentProps: {
placeholder: '请输入密码',
},
rules: z.string().min(6, '密码至少6个字符'),
required: true,
},
{
fieldName: 'remember',
label: '记住我',
component: 'VbenCheckbox',
defaultValue: false,
},
];
const handleSubmit = (values) => {
console.log('表单提交:', values);
};
const handleReset = () => {
console.log('表单重置');
};
</script>
表单布局示例
<template>
<div class="p-4">
<h2 class="mb-4 text-lg font-bold">表单布局</h2>
<div class="mb-4">
<span class="mr-4">布局方式:</span>
<label class="mr-2">
<input type="radio" v-model="layout" value="horizontal" /> 水平
</label>
<label>
<input type="radio" v-model="layout" value="vertical" /> 垂直
</label>
</div>
<VbenForm
v-model="formData"
:schema="schema"
:layout="layout"
:wrapperClass="wrapperClass"
/>
</div>
</template>
<script setup lang="ts">
import { VbenForm } from '@cimom/vben-core-ui-kit-form-ui';
import { ref } from 'vue';
const layout = ref('horizontal');
const wrapperClass = ref('grid-cols-1 md:grid-cols-2');
const formData = ref({
name: '',
age: '',
address: '',
email: '',
});
const schema = [
{
fieldName: 'name',
label: '姓名',
component: 'VbenInput',
},
{
fieldName: 'age',
label: '年龄',
component: 'VbenInput',
},
{
fieldName: 'address',
label: '地址',
component: 'VbenInput',
formItemClass: 'md:col-span-2',
},
{
fieldName: 'email',
label: '邮箱',
component: 'VbenInput',
formItemClass: 'md:col-span-2',
},
];
</script>