背景
新起Vue3项目表单组件编写没有表单组件封装,表单编写大量的重复el-col、el-form-item等组件,费时费力,大篇幅代码也不利于维护。这里基于Vue2及之前无为低代码平台的一些经验,封装了一份Vue3+Ts版本的配置化表单基础组件。
你已经是一个成熟的表单了,你要学会:
- 配置化渲染
- 布局支持(单列、双列、多列)
- 支持表单验证
- 支持配置动态调整
- 配置常用字段代码提示
- 兼容element-plus(推荐)、Ant Design Vue所有原生配置项
- 支持自定义组件
- 表单字段过多时支持收起/展开
此组件在element-ui、ant-design-vue项目中均可直接使用,实现原理vue3+ts组件库同时兼容多种ui框架
效果图
最终实现的效果是这样滴!!!
概要实现逻辑
组件目录
"食用"例子
我们先看下上述效果图的配置化JOSN实例,最终我们将实现所有表单都能通过这样一个表单JSON实现渲染,表单需要的属性,统统放入json里面,最后通过一个简单的调用即可渲染一个form表单
调用
<BaseForm
ref="BaseFormRef"
v-model="form"
class="BaseForm"
:config="config"
/>
<script lang="tsx" setup>
// 表单值
const form = ref<any>({})
// 表单配置json
const config = reactive<formConfig>(...)
</script>
上述编码我们即可渲染一个from表单
接口定义
先看配置JSON对象ts接口定义
/*
* @Author: 陈宇环
* @Date: 2022-05-30 14:29:12
* @LastEditTime: 2023-04-20 21:04:32
* @LastEditors: 陈宇环
* @Description:
*/
// 表单组件config配置接口
export interface formConfig {
columns: columnsBase[] // 表单项配置
colNum?: number // columns项默认宽度(1-24整数)
labelWidth?: string // label宽度
disabled?: boolean // 是否禁用
loading?: boolean // 是否加载中
notOpBtn?: boolean // 不需要(搜索,重置,导出)操作按钮
opBtnCol?: number // 操作按钮col宽度(24等分)
isSearch?: boolean // 是否需要搜索按钮
searchFn?: () => any // 搜索按钮点击触发函数
isExport?: boolean // 是否需要导出按钮
exportFn?: () => any // 搜索按钮点击触发函数
isReset?: boolean // 是否需要重置按钮
resetFn?: () => any // 搜索按钮点击触发函数
isExpand?: boolean // 是否需要展示/收起按钮
appendOpBtn?: () => any | void // 附加操作按钮render
nativeProps?: { // ui框架原生属性
[key: string]: any
}
}
// 所有表单控件的联合类型
export type columnsBase =
| inputProps
| selectProps
| radioProps
| checkboxProps
| numberProps
| dateProps
| dateRangeProps
| numberRangeProps
| cascaderProps
| switchProps
| uploadProps
| textProps
| renderProps
// 基础属性接口
interface defaultProps {
prop: string // key值
label?: string // label值
colNum?: number // 列宽 24等分
labelWidth?: number | string // label宽度
hide?: boolean // 是否隐藏(隐藏直接销毁dom)
disabled?: boolean // 是否禁用
required?: boolean // 是否必填
placeholder?: string // 描述字符
clearable?: boolean // 是否需要清除按钮
expandDefault?: boolean // 该字段展开收起默认值
prop2?: string // 附加字段(部分selelct等需要绑定两个key)
rules?: any[] // 附加检验规则
change?: (e: any) => void // change事件触发函数
nativeProps?: { // ui框架原生属性
[key: string]: any
}
}
// options选项 select、radio、checkbox、cascader(可能包含children)选项接口
export type optionsType = {
[label: string]: any, children?: any[]
}[] // 直接传数组对象
| { type: 'dic'; key: string } // 字典获取
| { // 接口获取
type: 'api'
getData: () => Promise<{ [label: string]: any, children?: any[] }[]> // 必须返回对象数组,不一定是label,value格式
}
// select、radio、checkbox 选项格式化函数(对应element-plus组件插槽)
export type format = (item: any) => any
// 输入框控件props
export interface inputProps extends defaultProps {
type: 'input' | 'textarea' | 'password' // 这里还能添加很多类型 参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types
showPassword?: boolean // 是否需要密码*号 显示隐藏开关
minlength?: number
maxlength?: number
rows?: number // textarea 行数
}
// 数字输入控件
export interface numberProps extends defaultProps {
type: 'number'
min?: number
max?: number
step?: number
precision?: number
controls?: boolean
}
// 下拉菜单控件props