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输入框属性open in new window
InputPassword密码输入框属性open in new window
InputTextArea文本域属性open in new window
InputNumber数值输入框属性open in new window
Select下拉框属性open in new window
TreeSelect树下拉选择属性open in new window
RadioGroup单选框组属性open in new window
CheckboxGroup多选框组属性open in new window
Cascader级联选择属性open in new window
DatePicker日期选择框属性open in new window
MonthPicker月份选择属性open in new window
WeekPicker周选择属性open in new window
RangePicker日期时间范围选择属性open in new window
RangeDate日期范围选择属性open in new window
Slider滑动输入条属性open in new window
Rate评分属性open in new window
Divider分割线属性open in new window

框架自定义控件

控件名控件描述对应文档
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

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>

API

详见:Form 表单组件 | Vben Adminopen in new window