ant-base-form的使用


本人封装了一个基于 ant 的 form 表单,以下是使用方法

表单属性

属性名 解释
fields 规定你需要生成表单的值结构
formLayout 表单布局
defaultSpan 你的表单默认占用宽度
ref 获取表单的 ref,用于提交按钮
initialValues 初始值,用于表单回显以及表单重置
formRules 自定义校验表单

fields 属性配置

fields是一个数组对象结构

通用

属性名 解释 类型
name 绑定的数据名 string
label 左侧名称 string
type 数据类型 string
required 星星,只起到展示左右(主要是为插槽校验考虑) boolean
errorMessage 必填错误信息 string
requiredFlag 确定是否为必填项 boolean
componentProps ant 组件本身自带的属性 Object
span 表单占用宽度,取值这个即不会取值默认 number
slot 插槽 boolean
dependency 根据前面的表单选中的内容而决定是否展示 { dependsOn: “根据那个表单的类型,绑定他的值”, value: “当前面绑定的值为某个时,显示这个表单的值”,}
slotFlag 不使用表单 a-form-item 的插槽 true 则不使用

type 类型

Type 类型 默认是 input 原生 解释 数据格式
input a-input 输入框
input-number a-input-number 数字输入框
select a-select 下拉框
radio a-radio 单选
checkbox a-checkbox 多选
cascader a-cascader 级联 [{}]
date a-date 日期
switch a-switch 开关
time a-time 时间 HH:mm:ss
textarea a-textarea 文本域
imgUpload a-upload 原本的上传包括了图片上传以及文件上传,html 结构和样式无法统一,因此建议使用插槽去做,不要使用组件
treeSelect a-tree-select tree 的下拉

以下是需要注意的点

time 类型注意点

time类型需要下载 ant datajs,并且需要导入且按照他的定义格式,我个人觉得太麻烦了,通过绑定value-format="HH:mm:ss"这个值去定义会好很多,例如

{
      name: "time",
      label: "时间",
      type: "time",
      componentProps: { "value-format": "HH:mm:ss" },
  },

cascader 注意点

在使用级联选择器时,当父亲的宽度低于子孙原生宽度时,报错ResizeObserver loop limit exceeded ,由于他是由递归写成的,结构的改变会导致他的不断的回流,直到报错。

解决办法:

在给他赋值初始值为 cascader: [{}],亦或者忽略

select 注意点

在我们使用 select 组件时,一般需要会需要自定义 label,value,options 字段,这这里面如何处理?直接使用 ant 的属性即可

componentProps: {
           "field-names": { label: "name", value: "id", options: "children" }
       }

cascader,treeSelect组件同理(使用名 fieldNames)

checkbox 与 radio

checkbox 有时会包住a-checkbox使用,由于代码底层使用的动态组件,我并未对其封装,如果需要用,请使用插槽,平常用法:

componentProps: {
  options: [数据]
}

radio 同理

required&errorMessage&requiredFlag 解释

这两个属性是相辅相成的,需要同时进行,required 并非真正的进行校验。而是只是有个必选的星号在那里,处理逻辑并未沿用 ant 组件内部校验,而是通过自己的业务逻辑去判断并产生消息提示

requiredFlag需定义才能开启校验,required 只是星号,主要是为了插槽的表单做校验

errorMessage不是必须的,底层做了保底,如果不传,则会采用默认信息提示

插槽表单如何校验?

1.插槽表单无需定义 required&errorMessage,只需要 required,让他把星号展示出来。

2.在提交按钮校验后去判断他这个值并进行校验

示例:

baseForm.value.handleSubmit((formData: Record<string, any>) => {
    if (!baseForm.value.formData.memberProjectCategoryId) {
          message.error("项目分类不能为空");
              return;
    }
   // 调用接口
    });
});

componentProps

componentProps可以说是最重要的,打个比方,我写一个文本域,即备注表单,我们需要如何定义fields配置。

const fields = ref([
    name:'remark',            // 绑定值
    label:'备注',              // 左侧标题
    type:'textarea',          // 表单类型
    required:true,            // 是否校验
    errorMessage:'请填写备注'   // 校验信息
])

这样,一条表单就配置好了。但是此时你想要把文本域展示默认值,同时控制在 2-4 行,同时限制他的字数,并显示剩余字数,如何处理?使用componentProps这个属性,继上面的代码继续

const fields = ref([
    name:'remark',            // 绑定值
    label:'备注',              // 左侧标题
    type:'textarea',          // 表单类型
    required:true,            // 是否校验
    errorMessage:'请填写备注',   // 校验信息
    componentProps:{
         "auto-size": { minRows: 2, maxRows: 4 },   // 控制在2-4行
          maxlength: 10,                            // 最大字数
          placeholder: "文本",                       // 默认文本
          "show-count": true                        // 展示剩余数字
    }
])

注意:对象的键,原本就是字符串,因此我们对于带 - 的属性把他写成字符串即可

这样就 ok 了,componentProps中的属性均来自 ant 组件,想要加什么效果加好了即可。

span 属性

共 24 份,设置了span这个值,将替代默认defaultSpan

slot 属性

slot即插槽,他的值为布尔值,true 为开启插槽,反正不开启,如何使用?

比如你想要在某条表单后面写入插槽,只需要在fields将他定义在那条数据的后面即可,例如:

第一步 定义

const fields: Field[] = [
  {
    name: 'username',
    label: 'Username',
    type: 'input',
    errorMessage: '请输入姓名',
    required: true,
    span: 12,
  },
  {
    name: 'sex',
    label: '性别',
    type: 'input',
    errorMessage: '请输入性别',
    required: true,
    slot: true,
    span: '12',
  },
]

以上示例即把性别插入姓名后方,如果需要插入到他的前面,即需要把数据放在他的前面即可

第二步 使用

<CustomForm
  ref="customForm"
  :fields="fields"
  formLayout="vertical"
  :initialValues="initialValues"
  :defaultSpan="8"
>
          <template #sex="{ field, formData }">
              <div>
                  <a-input v-model:value="formData.sex" placeholder="你好"></a-input>
              </div>
          </template>
</CustomForm>

看示例,作用域插槽绑定的插槽名,就是你定义的那条数据的name属性值,#sex, 同时你可以在你插入的内容中绑定数据,作用域插槽把数据都给你传递回来了,如何绑定?formData是用于回显的数据对象,给他绑定上对应,即:formData就是initialValues

formLayout

formLayout 就是 form 表单如何布局,ant 给了三种属性值 分别是

horizontal 默认值
vertical
inline

defaultSpan

defaultSpan 就是你表单默认占多少位置,如果数据设置了 span,则会被替换掉,默认值是 24 份

initialValues

initialValues 是数据初始值,可以用于数据初始化及数据回显

ref

用于获取表单的实例对象,用于表单的提交,可以通过他拿到所填数据,以及数据校验

const customForm = ref()
const onSubmit = () => {
  customForm.value.handleSubmit((formData: Record<string, any>) => {
    console.log('Form Submitted:', formData)
  })
}

formData就是你提交表单所需数据

dependency

用于根据前面表单的数据动态展示后面的表单
dependsOn: 绑定哪个表单? 他的值写绑定表单的绑定值
value:绑定表单选中某个值显示

  dependency: {
            dependsOn: "radioValue",
            value: "female",
  }

// 选中radioValue值,当他的值为female,则显示

slotFlag

这个主要是作用域表单的隐藏与显示,可以作为动态表单,slot 插槽隐藏时,会有一块占地区域,如果不想要,则使用 slotFlag,且自己在外部套用一层 a-form-item

// 使用slot的插槽 隐藏占用位置
<template #associationProjectCode="{ field, formData }">
  <a-select
    v-model:value="formData.associationProjectCode"
    optionLabelProp="label"
    show-search
    placeholder="请选择诊疗项目"
    :default-active-first-option="false"
    :show-arrow="false"
    :filter-option="false"
    :not-found-content="null"
    :options="option"
    @search="handleSearch"
    @change="handleChange"
  ></a-select>
</template>

// 使用slotFlag的插槽 隐藏不占位置 建议在使用表单的事件时使用
<template v-if="treeId == 0" #memberProjectCategoryId="{ field, formData }">
  <a-form-item
    :label="field.label"
    :required="field.required"
    :name="field.formName"
  >
    <a-select
      v-model:value="formData.memberProjectCategoryId"
      optionLabelProp="label"
      show-search
      placeholder="请选择诊疗项目"
      :default-active-first-option="false"
      :show-arrow="false"
      :filter-option="false"
      :not-found-content="null"
      :options="options"
      @search="handleSearch"
      @change="handleChange"
    ></a-select>
  </a-form-item>
</template>

动态表单建议使用 dependency,而不是使用 slotFlag,如果需要触发表单的某个事件时,使用 slotFlag.

formRules

用于自定义表单,需要配合 formName 使用

{
    name: "username",
    label: "姓名",
    type: "input",
    span: 12,
    formName: "username",
},
const formRules = {
  username: [
    {
      required: true,
      message: 'Please input Activity name',
      trigger: 'change',
    },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ],
}

5.下载使用

1.下载

npm i ant-base-form   //下载

2.在 main.ts 引入

import BaseForm from 'ant-base-form'
import 'ant-base-form/dist/style.css'

const app = createApp(App)
app.use(BaseForm)

注意,如若样式结构出现问题,则需要将 ant 组件库及样式先引入,再引入这个,同时使用是也放在 ant 后,如若未出现,则正常使用

3.在需要使用的组件中使用

<template>
  <BaseForm
    ref="baseForm"
    :fields="fields"
    formLayout="vertical"
    :initialValues="initialValues"
    :defaultSpan="8"
  >
    // 插槽
    <template #sex="{ field, formData }">
      <div>
        <a-input v-model:value="formData.sex" placeholder="你好"></a-input>
      </div>
    </template>
  </BaseForm>
</template>

<script lang="ts" setup>
// 初始值
const initialValues = {
  username: '',
  sex: '',
  aaaa: '',
}

// 生成表单类型
const fields = [
  {
    name: 'username',
    label: 'Username',
    type: 'input',
    errorMessage: '请输入姓名',
    required: true,
    span: 12,
  },
  {
    name: 'sex',
    label: '性别',
    type: 'input',
    errorMessage: '请输入性别',
    required: true,
    slot: true,
    span: '24',
  },
  {
    name: 'aaaa',
    label: 'aaaaa',
    type: 'textarea',
    componentProps: {
      'auto-size': { minRows: 5, maxRows: 5 },
      maxlength: 10,
      placeholder: '文本',
      'show-count': true,
    },
  },
]

// 点击提交  拿到表单数据
const baseForm = ref()

// 绑定表单的按钮,用于数据校验以及拿到数据
const onSubmit = () => {
  baseForm.value.handleSubmit((formData: Record<string, any>) => {
    console.log('Form Submitted:', formData)
  })
}
</script>

6.示例

// 初始值
const initialValues = {
  username: '',
  area: '',
  date: undefined,
  flag: true,
  checkbox: [],
  radio: '',
  remark: '',
}

// 生成表单类型
const fields: any = [
  {
    name: 'username',
    label: '姓名',
    type: 'input',
    span: 12,
    formName: 'username',
  },
  {
    name: 'area',
    label: '地区',
    type: 'select',
    span: '12',
    formName: 'area',
    componentProps: {
      options: [
        { label: '苹果', value: 'Apple' },
        { label: '梨', value: 'Pear' },
        { label: '橘子', value: 'Orange' },
      ],
    },
  },
  {
    name: 'date',
    label: '时间',
    type: 'date',
    span: '12',
    formName: 'date',
    componentProps: {
      format: 'YYYY/MM/DD',
    },
    forName: 'date',
  },
  {
    name: 'flag',
    label: '开关',
    type: 'switch',
    span: '12',
  },
  {
    name: 'checkbox',
    label: '多选',
    type: 'checkbox',
    span: '12',
    componentProps: {
      options: [
        { label: '苹果', value: 'Apple' },
        { label: '梨', value: 'Pear' },
        { label: '橘子', value: 'Orange' },
      ],
    },
  },
  {
    name: 'radio',
    label: '单选',
    type: 'radio',
    span: '12',
    componentProps: {
      options: [
        { label: '苹果', value: 'Apple' },
        { label: '梨', value: 'Pear' },
        { label: '橘子', value: 'Orange' },
      ],
    },
  },
  {
    name: 'remark',
    label: '备注',
    type: 'textarea',
    span: '12',
  },
]

const formRules = {
  username: [
    {
      required: true,
      message: 'Please input Activity name',
      trigger: 'change',
    },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ],
  area: [
    {
      required: true,
      message: 'Please select Activity zone',
      trigger: 'change',
    },
  ],
  date: [
    {
      required: true,
      message: 'Please pick a date',
      trigger: 'change',
      type: 'object',
    },
  ],
}

// 点击提交  拿到表单数据
const baseForm = ref()

// 表单自定义校验
const onSubmit1 = () => {
  baseForm.value.customRuleSubmit((formData: Record<string, any>) => {
    console.log('Form Submitted:', formData)
  })
}

7.数据重置

baseForm.value.resetForm()

8.数据回显

baseForm.value.dataPlayBack(回显数据对象)

9.数据回显定义某一个数据或更改某一个数据

baseForm.value.formData.属性值 = 数据

文章作者: 冷杨威
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冷杨威 !
  目录
-->