表单组件

概述

表单组件是一套基于 Element Plus 封装的表单解决方案,提供了丰富的表单控件和灵活的配置方式。通过 schema 配置即可快速构建复杂的表单界面,支持表单验证、联动、动态显示等功能。

基础用法

1. 引入组件

import { BasicForm, useForm } from '@/components/form'

2. 定义表单结构

const schema: FormItemSchema[] = [
  {
    prop: 'name',
    label: '姓名',
    component: 'Input',
    colSpan: 12,
    defaultValue: '',
    rules: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  },
  {
    prop: 'email',
    label: '邮箱',
    component: 'Input',
    colSpan: 12,
    componentProps: {
      placeholder: '请输入邮箱地址'
    }
  }
]

const [BasicForm, formApi] = useForm({
  labelPosition: 'right',
  labelWidth: '100px',
  schema: schema
})

3. 在模板中使用

<template>
  <BasicForm @submit="handleSubmit" @reset="handleReset" />
</template>

核心概念

FormSchema 表单配置

属性类型说明
labelPosition'left' | 'right' | 'top'标签位置
gutternumber栅格间隔
labelWidthstring标签宽度
schemaFormItemSchema[]表单项配置
showDefaultActionsboolean是否显示默认操作按钮
submitButtonTextstring提交按钮文本
resetButtonTextstring重置按钮文本
rulesRecord<string, any>表单验证规则
inlineboolean是否行内表单

FormItemSchema 表单项配置

属性类型说明
propstring表单项属性名(必填)
labelstring表单项标签(必填)
componentstring表单项组件类型
defaultValueany表单项默认值
componentPropsRecord<string, any> | Function组件属性
colSpannumber栅格列数(1-24)
rulesArray表单项验证规则
ifShowboolean | Function动态显示控制(JS控制)
showboolean | Function动态显示控制(CSS控制)
helpMessagestring | string[]帮助提示信息
ifDetailboolean | Function详情表单显示控制

内置组件

基础组件

  1. Input - 文本输入框
{
  prop: 'input',
  label: '单行文本',
  component: 'Input',
  componentProps: { 
    type: 'text',
    placeholder: '请输入内容'
  }
}
  1. InputNumber - 数字输入框
{
  prop: 'number',
  label: '数字',
  component: 'InputNumber'
}
  1. Select - 下拉选择框
{
  prop: 'select',
  label: '下拉选择',
  component: 'Select',
  componentProps: {
    options: [
      { label: '选项1', value: '1' },
      { label: '选项2', value: '2' }
    ]
  }
}
  1. RadioGroup - 单选框组
{
  prop: 'radio',
  label: '单选框',
  component: 'RadioGroup',
  componentProps: {
    options: [
      { label: '选项1', value: '1' },
      { label: '选项2', value: '2' }
    ]
  }
}
  1. CheckboxGroup - 多选框组
{
  prop: 'checkbox',
  label: '多选框',
  component: 'CheckboxGroup',
  componentProps: {
    options: [
      { label: '选项1', value: '1' },
      { label: '选项2', value: '2' }
    ]
  }
}

远程数据组件

  1. ApiSelect - 远程下拉选择
{
  prop: 'apiSelect',
  label: '远程下拉',
  component: 'ApiSelect',
  componentProps: {
    api: '/api/data/select'
  }
}
  1. ApiRadioGroup - 远程单选框
{
  prop: 'apiRadio',
  label: '远程单选',
  component: 'ApiRadioGroup',
  componentProps: {
    api: '/api/data/select'
  }
}
  1. ApiCheckboxGroup - 远程多选框
{
  prop: 'apiCheckbox',
  label: '远程多选',
  component: 'ApiCheckboxGroup',
  componentProps: {
    api: '/api/data/select'
  }
}
  1. ApiTreeSelect - 远程树形选择
{
  prop: 'apiTree',
  label: '远程树选择',
  component: 'ApiTreeSelect',
  componentProps: {
    api: '/api/tree/data'
  }
}
  1. ApiCascader - 远程级联选择
{
  prop: 'apiCascader',
  label: '远程级联',
  component: 'ApiCascader',
  componentProps: {
    api: '/api/cascader/data'
  }
}

字典组件

{
  prop: 'dict',
  label: '字典组件',
  component: 'ApiDict',
  componentProps: {
    code: 'sex',
    renderType: 'Select' // Select/RadioGroup/CheckboxGroup
  }
}

日期组件

{
  prop: 'date',
  label: '日期选择',
  component: 'DatePicker',
  componentProps: {
    type: 'date' // date/datetime/daterange/datetimerange等
  }
}

其他组件

  1. Upload - 文件上传
{
  prop: 'upload',
  label: '文件上传',
  component: 'Upload',
  componentProps: {
    listType: 'picture-card'
  }
}
  1. Editor - 富文本编辑器
{
  prop: 'content',
  label: '内容',
  component: 'Editor'
}
  1. IconPicker - 图标选择器
{
  prop: 'icon',
  label: '图标',
  component: 'IconPicker'
}

高级功能

表单联动

通过 ifShowshow 属性实现表单联动:

{
  prop: 'type',
  label: '类型',
  component: 'RadioGroup',
  componentProps: {
    options: [
      { label: '类型1', value: 1 },
      { label: '类型2', value: 2 }
    ]
  }
},
{
  prop: 'field1',
  label: '字段1',
  component: 'Input',
  ifShow: (values) => values.type === 1 // 当type为1时显示
},
{
  prop: 'field2',
  label: '字段2',
  component: 'Input',
  show: (values) => values.type === 2 // 当type为2时显示(CSS控制显示隐藏)
}

动态属性

通过函数形式的 componentProps 实现动态属性:

{
  prop: 'password',
  label: '密码',
  component: 'Input',
  componentProps: (values) => {
    return {
      type: 'password',
      disabled: values.status === 'disabled'
    }
  }
}

表单方法

通过 useForm返回的 formApi 可以调用以下方法:

const [BasicForm, formApi] = useForm(schema)

// 表单验证
formApi.validate()

// 获取表单值
formApi.getValues()

// 设置表单值
formApi.setValues({ name: 'test' })

// 重置表单
formApi.resetFields()

// 更新表单项配置
formApi.updateSchema({
  prop: 'name',
  componentProps: { placeholder: '新占位符' }
})

完整示例

<template>
  <div>
    <el-radio-group v-model="labelPosition">
      <el-radio-button value="left">左对齐</el-radio-button>
      <el-radio-button value="right">右对齐</el-radio-button>
      <el-radio-button value="top">顶部对齐</el-radio-button>
    </el-radio-group>
    
    <BasicForm 
      style="margin-top: 12px" 
      @submit="handleSubmit" 
      @reset="handleReset"
      @change="handleChange" 
    />
    
    <!-- 显示表单数据 -->
    <code>
      <pre>{{ JSON.stringify(formData, null, 2) }}</pre>
    </code>
  </div>
</template>

<script setup lang="ts">
import { useForm } from '@/components/form'

const labelPosition = ref<'left' | 'right' | 'top'>('right')
const formData = ref({})

const schema = [
  {
    prop: 'name',
    label: '姓名',
    component: 'Input',
    colSpan: 12,
    rules: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  },
  {
    prop: 'email',
    label: '邮箱',
    component: 'Input',
    colSpan: 12
  },
  {
    prop: 'status',
    label: '状态',
    component: 'RadioGroup',
    componentProps: {
      options: [
        { label: '启用', value: 1 },
        { label: '禁用', value: 0 }
      ]
    }
  },
  {
    prop: 'remark',
    label: '备注',
    component: 'Input',
    colSpan: 24,
    componentProps: { type: 'textarea', rows: 4 }
  }
]

const [BasicForm, formApi] = useForm({
  labelPosition: labelPosition.value,
  labelWidth: '100px',
  schema: schema
})

// 监听标签位置变化
watch(() => labelPosition.value, (val) => {
  formApi.setState({ labelPosition: val })
})

// 表单提交
const handleSubmit = async (values: any) => {
  console.log('表单提交:', values)
}

// 表单重置
const handleReset = () => {
  console.log('表单重置')
}

// 表单值变化
const handleChange = (values: any) => {
  formData.value = values
}
</script>

注意事项

  1. 所有表单项必须包含 proplabel 属性
  2. 使用远程数据组件时,确保 API 返回的数据格式符合要求
  3. 表单联动时,ifShow会移除 DOM 元素,show 仅控制显示隐藏
  4. 通过 componentProps 可以传递任何组件支持的属性,具体看src/components/form/components/*,和ElementPlus默认的属性,具体可以看Element-Plusopen in new window文档