Skip to content
文章目录

动态表单与动态表格设计套路

需要提前掌握的知识

重要说明

如果自定义v-model实际是一个对象,而组件内部会对 v-model 值的某些属性值进行修改, 那么不要将 v-model 的值设置为 nullundefined,然后再通过 withDefaults() 的形式,将 v-model 对应 props设置为 空对象或特定对象, 因为这将导致v-model无法进行响应式。表现形式就是。内部更新了v-model属性值,但界面实际无变化

动态表单哪些东西是动态的?

  • 表单项可能是动态的
  • 表单项的可选值可能是动态的
  • 表单的验证规则也可能是动态的

实现套路

  1. 定义表单项配置
  2. 通过import.mate.glob加载指定目录的所有表单项组件
  3. 将所有的表单项配置成一个数组
  4. 循环表单项配置数组,动态渲染成一个表单

一个完整的动态表单项配置

ts
import { FormItemRule } from 'element-plus'
import { Component } from 'vue'

/**
 * 表单项规则创建函数
 *
 * @param formData 表单数据
 * @param rowData 行数据
 *
 * @return  {FormItemRule[] | undefined}  规则数组或undefined
 */
type RuleFactory<T extends DynFormData> = (
  formData: T,
  rowData?: Record<string, unknown>
) => FormItemRule[] | FormItemRule | undefined

/**
 * 可选项
 */
export interface OptionType {
  label: string
  value: number | string
}
export type DynFormData = Record<string, unknown>
/**
 * 表单项配置
 */
export interface FormItemConfig<T extends DynFormData> extends Record<string, unknown> {
  /**
   * el-form-item标签的prop
   */
  prop: string
  /**
   * 表单项的组件类型. 不传表示ElInput
   */
  type?: string
  /**
   * 组件lable
   */
  label: string
  /**
   * 表单项验证规则
   */
  rules?: FormItemRule | FormItemRule[] | RuleFactory<T>
  /**
   * 表单项目前置验证规则(用于后台动态添加验证规则)
   */
  prepositiveRules?: FormItemRule[]
  /**
   * 可选项数组
   */
  optionArr?: OptionType[]
  /**
   * 占位符
   */
  placeholder?: string
  /**
   * 表单项自定义props
   */
  customProps?: { [key: string]: unknown }
  /**
   * 表单项组件自定义事件
   *
   * @param   {unknown}  evtData  自定义事件的数据
   *
   */
  customEvt?: Record<string, (...args: any | undefined) => void>
  /**
   * 当前表单项是否需要显示. 默认:true
   */
  needRender?: NeedRender
}

export type DynFormConfig<T extends DynFormData> = Record<string, FormItemConfig<T>>

export type NeedRenderFun = (formData: DynFormData) => boolean
export type NeedRender = NeedRenderFun | boolean

/**
 * 动态项组件加载方法(该方法用于获取动态项组件实例)
 *
 * vite通过 import.meta.glob 方式获取
 *
 * 返回值map的key为动态项标识,value为动态项组件
 */
export type DynCompLoadMethod = () => Map<string, Component>

/**
 * 表单项目组件公共props
 */
export interface DynFormItemCompProps {
  /**
   * 表单数据
   */
  formData: DynFormData
  /**
   * 表单项字段
   */
  prop: string
  /**
   * 表单项目值. 需定义为v-model
   */
  value?: string
  placeholder?: string
  /**
   * 可选列表。用于类似select的组件
   */
  optionArr?: OptionType[]
}

/**
 * 表单项标记有误
 */
interface FormItemMarkError {
  /**
   * 表单项标识
   */
  field: string
  /**
   * 错误提示信息
   */
  errorMsg: string
}

/**
 * 表单标记有误信息
 */
type FormMarkErrors = Record<string, string | Record<string, string>>

普通动态表单

下拉选择值,控制关联文本可见性

下拉选择值,控制关联动态下拉选项

下拉选择值,控制日期范围验证规则

日期范围的动态验证规则如下:

  • 日期范围表单项在下拉选择表单项无值时,非必填
  • 日期范围表单项在下拉选择表单项有值时,必填且开始日期必须在当前年的 1 月 15 日

主要交互逻辑如下:

  • 下拉选择表单项改变时,则验证日期范围表单项
  • 下拉选择表单项清空时,则清除日期范围表单项的验证错误提示

后端控制表单项是否展示和必填

扩展:只读与可编辑切换, 恢复编辑前数据

扩展:标记有误

  • 对表单项填写值进行标记有误
  • 清除指定表单项的标记有误
  • 取消编辑时恢复标记有误
  • 对标记有误字段进行是否改为了不同值进行验证

动态表格有哪些东西是动态的

  • 列是动态的

普通动态表格

  • 爱好列使用了 formatter 进行了值显示格式化
  • 操作列通过自定义组件完成渲染,并支持 del 事件

扩展:动态表格结合的行编辑动态表单

扩展:标记有误

参考资料

再也不想写表单了

zelda_player / eleme-plus-crud

$listeners 被 Vue3 抛弃了,那它的活儿谁来接?

vue3 组件传值之 props 与 attrs 的区别