基于vue3+ts配置化form表单组件实现浅析

本文介绍了如何基于Vue3和Typescript实现一个高度配置化的表单组件,支持布局、验证、UI框架兼容及自定义组件。通过JSON配置实现表单渲染,减少重复代码,提高维护性。文章包含组件实现逻辑、接口定义、示例代码及遇到的坑点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

新起Vue3项目表单组件编写没有表单组件封装,表单编写大量的重复el-col、el-form-item等组件,费时费力,大篇幅代码也不利于维护。这里基于Vue2及之前无为低代码平台的一些经验,封装了一份Vue3+Ts版本的配置化表单基础组件。

你已经是一个成熟的表单了,你要学会:

  • 配置化渲染
  • 布局支持(单列、双列、多列)
  • 支持表单验证
  • 支持配置动态调整
  • 配置常用字段代码提示
  • 兼容element-plus(推荐)、Ant Design Vue所有原生配置项
  • 支持自定义组件
  • 表单字段过多时支持收起/展开

此组件在element-uiant-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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值