BasicForm 表单
BasicForm对ant design的form组件进行了高度的封装,可以通过配置FormSchemas来达到配置表单的目的。
注:因为进行了高度封装,可能会丢失一些灵活性,如果在非常复杂的场景,建议使用ant design原生的写法。
使用场景
- 快速创建一个表单和提交表单数据。
- 需要对表单的控件字段进行输入校验。
基本用法
<template>
<PageWrapper>
<BasicForm @register="register" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入备注',
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
</script>
属性说明
- field 字段名
- label 字段描述
- component 组件名
- componentProps 组件属性
演示Select控件的使用
<template>
<PageWrapper>
<BasicForm @register="register" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入备注',
},
},
{
field: 'type',
label: '选择类型',
component: 'Select',
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '类型1',
value: 1,
},
{
label: '类型2',
value: 2,
},
{
label: '类型3',
value: 3,
},
],
getPopupContainer: () => document.body,
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
</script>
注意,如果下拉选择错位,可以追加getPopupContainer: () => document.body
配置
演示ApiSelect控件的使用
<template>
<PageWrapper>
<BasicForm @register="register" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
import { sysUserSelect } from '/@/api/sys/user';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'type',
label: '类型',
component: 'Select', // Select选择组件
componentProps: {
placeholder: '请选择类型',
allowClear: false,
bordered: true,
options: [
{
label: '类型1',
value: 1,
},
{
label: '类型2',
value: 2,
},
{
label: '类型3',
value: 3,
},
],
},
},
{
field: 'userId',
label: '所属用户',
component: 'ApiSelect',
componentProps: {
placeholder: '请选择用户',
api: sysUserSelect,
params: {
test: 11,
},
},
},
{
field: 'postId',
label: '所属岗位',
component: 'ApiSelect',
componentProps: {
placeholder: '请选择岗位',
api: '/sys/post/select',
params: {
test: 11,
},
getPopupContainer: () => document.body,
},
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入备注',
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
</script>
注意,如果下拉选择错位,可以追加getPopupContainer: () => document.body
配置 错位图
表单控件清单
Ant Design Vue自带控件
控件名 | 控件描述 | 对应ant design文档 |
---|---|---|
Input | 输入框 | 属性 |
InputPassword | 密码输入框 | 属性 |
InputTextArea | 文本域 | 属性 |
InputNumber | 数值输入框 | 属性 |
Select | 下拉框 | 属性 |
TreeSelect | 树下拉选择 | 属性 |
RadioGroup | 单选框组 | 属性 |
CheckboxGroup | 多选框组 | 属性 |
Cascader | 级联选择 | 属性 |
DatePicker | 日期选择框 | 属性 |
MonthPicker | 月份选择 | 属性 |
WeekPicker | 周选择 | 属性 |
RangePicker | 日期时间范围选择 | 属性 |
RangeDate | 日期范围选择 | 属性 |
Slider | 滑动输入条 | 属性 |
Rate | 评分 | 属性 |
Divider | 分割线 | 属性 |
框架自定义控件
控件名 | 控件描述 | 对应文档 |
---|---|---|
ApiDict | 字典 | - code 字典编码 - dateType 唯一编码 |
ApiSelect | 远程下拉加载组件 | - api 接口地址或函数 - params 接口参数。此属性改变时会自动重新加载接口数据 - resultField 接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式 - immediate 是否立即请求接口 |
ApiTreeSelect | 远程下拉树加载组件 | - api 接口地址或函数 - params 接口参数。此属性改变时会自动重新加载接口数据 - resultField 接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式 - immediate 是否立即请求接口 |
Upload | 上传组件 | |
IconPicker | 图标选择 |
组件的显示、隐藏与动态禁用
<template>
<PageWrapper>
<BasicForm @register="register" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
import { sysUserSelect } from '/@/api/sys/user';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'type',
label: '类型',
component: 'Select', // Select选择组件
componentProps: {
placeholder: '请选择类型',
allowClear: false,
bordered: true,
options: [
{
label: '类型1',
value: 1,
},
{
label: '类型2',
value: 2,
},
{
label: '类型3',
value: 3,
},
],
},
},
{
field: 'userId',
label: '所属用户',
component: 'ApiSelect',
componentProps: {
placeholder: '请选择用户',
api: sysUserSelect,
params: {
test: 11,
},
},
},
{
field: 'postId',
label: '所属岗位',
component: 'ApiSelect',
componentProps: {
placeholder: '请选择岗位',
api: '/sys/post/select',
params: {
test: 11,
},
getPopupContainer: () => document.body,
},
ifShow({ values }) {
return values.type == 2;
},
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入备注',
},
dynamicDisabled({ values }) {
return values.type == 3;
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
</script>
表单校验
<template>
<PageWrapper>
<BasicForm @register="register" @submit="handleSubmit" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
//自动触发检验,布尔类型
required: true,
//检验的时候不加上标题
// rulesMessageJoinLabel: false,
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'phone',
label: '手机号',
component: 'Input',
//支持正则表达式pattern 和 自定义提示信息 message
rules: [{ required: true, message: '请输入正确的手机号', pattern: /^1[3456789]\d{9}$/ }],
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入备注',
},
// 支持获取当前值判断触发 values代表当前表单的值
required: ({ values }) => {
return values.type == 2;
},
},
{
field: 'type',
label: '选择类型',
component: 'Select',
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '类型1',
value: 1,
},
{
label: '类型2',
value: 2,
},
{
label: '类型3',
value: 3,
},
],
getPopupContainer: () => document.body,
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
const handleSubmit = (values) => {
console.log(values);
};
</script>
自定义动态表单校验
<template>
<PageWrapper>
<BasicForm @register="register" @submit="handleSubmit" />
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
//自动触发检验,布尔类型
required: true,
//检验的时候不加上标题
// rulesMessageJoinLabel: false,
componentProps: {
placeholder: '请输入名称',
},
},
{
field: 'password',
label: '密码',
component: 'InputPassword',
required: true,
componentProps: {
placeholder: '请输入密码',
},
},
{
field: 'confirmPassword',
label: '确认密码',
component: 'InputPassword',
componentProps: {
placeholder: '请输入确认密码',
},
//动态自定义规则,values: 当前表单的所有值
dynamicRules: ({ values }) => {
console.log('values:', values);
//需要return
return [
{
//默认开启表单检验
required: true,
// value 当前输入的值
validator: (_, value) => {
//需要return 一个Promise对象
return new Promise((resolve, reject) => {
if (!value) {
reject('请输入确认密码!');
}
//验证两密码是否一致
if (values.password !== value) {
reject('两密码不一致!');
}
resolve();
});
},
},
];
},
},
{
field: 'type',
label: '选择类型',
component: 'Select',
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '类型1',
value: 1,
},
{
label: '类型2',
value: 2,
},
{
label: '类型3',
value: 3,
},
],
getPopupContainer: () => document.body,
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
});
const handleSubmit = (values) => {
console.log(values);
};
</script>
自定义组件
slot插槽的方式
<template>
<PageWrapper>
<BasicForm @register="register">
<template #tt-name="{ model, field }">
<a-input v-model:value="model[field]" placeholder="请输入名称" />
<span>自定义插槽方式</span>
</template>
</BasicForm>
</PageWrapper>
</template>
<script setup>
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
slot: 'tt-name',
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
onSubmit(values) {
console.log(values);
},
});
</script>
component的方式
后面课程再展开
自定义渲染的方式
<template>
<PageWrapper>
<BasicForm @register="register">
<template #tt-name="{ model, field }">
<a-input v-model:value="model[field]" placeholder="请输入名称" />
<span>自定义插槽方式</span>
</template>
</BasicForm>
</PageWrapper>
</template>
<script setup>
import { h } from 'vue';
import { Textarea } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form';
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
slot: 'tt-name',
},
{
field: 'remark',
label: '备注',
component: 'Input',
//model 表单对象,field 当前字段
render: ({ model, field }) => {
//渲染自定义组件,以Textarea为例
return h(Textarea, {
placeholder: '请输入备注',
value: model[field],
style: { width: '100%' },
onChange: (e) => {
model[field] = e.target.value;
},
});
},
},
];
const [register] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
onSubmit(values) {
console.log(values);
},
});
</script>
Slots
名称 | 说明 |
---|---|
formFooter | 表单底部区域 |
formHeader | 表单顶部区域 |
resetBefore | 重置按钮前 |
submitBefore | 提交按钮前 |
advanceBefore | 展开按钮前 |
advanceAfter | 展开按钮后 |
ref和methods
<template>
<PageWrapper>
<BasicForm @register="register" ref="formRef">
<template #tt-name="{ model, field }">
<a-input v-model:value="model[field]" placeholder="请输入名称" />
<span>自定义插槽方式</span>
</template>
</BasicForm>
</PageWrapper>
</template>
<script setup>
import { h, onMounted } from 'vue';
import { Textarea } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form';
const formRef = ref();
const schemas = [
{
field: 'name',
label: '名称',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
slot: 'tt-name',
},
{
field: 'remark',
label: '备注',
component: 'Input',
//model 单签表单对象,field 当前字段
render: ({ model, field }) => {
//渲染自定义组件,以Textarea为例
return h(Textarea, {
placeholder: '请输入备注',
value: model[field],
style: { width: '100%' },
onChange: (e) => {
model[field] = e.target.value;
},
});
},
},
];
const [register, methods] = useForm({
schemas: schemas,
submitButtonOptions: {
text: '提交',
},
onSubmit(values) {
console.log(values);
},
});
onMounted(() => {
console.log('formRef', formRef);
console.log('methods', methods);
});
</script>