Skip to content

PenForm 表单组件

支持的表单元素

  • Input 输入框
  • RadioGroup 单选框组
  • CheckboxGroup 多选框组
  • Select 下拉选择
  • InputNumber 数字输入框
  • Switch 开关
  • Divider 分割线

TIP

  1. 目前集成的只有上述常用的组件,因为集成太多不常用组件不利于体积的优化

  2. 除了以上的其他组件可以通过配置 typeCustom 结合插槽自定义实现,具体可参考下述代码示例

代码示例

vue
<template>
    <!-- 表单 -->
    <pen-form v-model="formData" :fields="formFields" label-width="100px">
        <template #birthday>
            <el-date-picker v-model="formData.birthday" type="date" placeholder="请选择日期"></el-date-picker>
        </template>
    </pen-form>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const formFields = defineForm([
  {
    type: Form.Divider,
    title: '基本信息',
    props: {
      contentPosition: 'left'
    }
  },
  {
    type: Form.Input,
    field: 'name',
    formItemProps: {
      label: '姓名',
    },
    props: {
      placeholder: '请输入姓名',
      clearable: true,
      onChange: (e: any) => {
        console.log(e)
      },
      onClear: () => {
        console.log('clear')
      }
    }
  },
  {
    type: Form.RadioGroup,
    field: 'sex',
    formItemProps: {
      label: '性别',
    },
    options: [
      { label: '男', value: '1' },
      { label: '女', value: '2' },
    ],
    labelField: 'label',
    valueField: 'value',
    radioProps: {
      border: true,
    }
  },
  {
    type: Form.Divider,
    title: '其他信息',
    props: {
      contentPosition: 'left'
    }
  },
  {
    type: Form.InputNumber,
    field: 'age',
    formItemProps: {
      label: '年龄',
    },
    props: {
      placeholder: '请输入年龄',
      min: 1,
      max: 120,
      precision: 0,
      controlsPosition: 'right',
      style: {
        width: '220px'
      }
    }
  },
  {
    type: Form.Custom,
    field: 'birthday',
    formItemProps: {
      label: '出生日期',
    },
    initValue: '',
  }
])

const { fields, initFormData } = generateFormData(formFields);
const { currentRow, formData, action, actionName, init } = useForm(
    initFormData, 
    (params) => {
      // 初始化逻辑
    }
)
</script>

插槽

插槽名说明
[field][field]为具体字段名,如:name,实现自定义表单元素

属性类型

ts
import type { FormProps } from 'element-plus';
interface Props extends Partial<FormProps> {
    fields: FormFieldItem[];
    modelValue: Record<string, any>;
}

FormFieldItem定义

ts
import type {
    InputProps,
    ISelectProps,
    RadioGroupProps,
    CheckboxGroupProps,
    SwitchProps,
    InputNumberProps,
    DividerProps,
    FormItemProps,
} from 'element-plus';
import type { CheckboxEventProps, ExtraProps, InputEventProps, InputNumberEventProps, RadioEventProps, SelectEventProps, SwitchEventProps } from '../../types';
import type { ComputedRef, Ref } from 'vue';

export enum Form {
    Input = 'ElInput',
    Select = 'Select',
    RadioGroup = 'RadioGroup',
    CheckboxGroup = 'CheckboxGroup',
    Switch = 'ElSwitch',
    InputNumber = 'ElInputNumber',
    TimePicker = 'ElTimePicker',
    DatePicker = 'ElDatePicker',
    Cascader = 'ElCascader',
    Custom = 'Custom',
    Divider = 'Divider'
}

type BaseForm<T> = {
    field: T;
    formItemProps:
    | (() => Partial<FormItemProps> & ExtraProps)
    | ComputedRef<Partial<FormItemProps> & ExtraProps>
    | Ref<Partial<FormItemProps> & ExtraProps>
    | (Partial<FormItemProps> & ExtraProps);
    visible?: boolean | (() => boolean) | Ref<boolean> | ComputedRef<boolean>;
}

type CommonProps = {
    initValue?: any;
    onChange?: (value: any) => void;
}

type OptionsProps = {
    options: any[] | (() => any[]) | Ref<any[]> | ComputedRef<any[]>;
    valueField: string;
    labelField: string;
}

export type InputForm<T> = BaseForm<T> & CommonProps & {
    type: Form.Input;
    props?:
    | (() => Partial<InputProps & ExtraProps> & InputEventProps)
    | Ref<Partial<InputProps & ExtraProps> & InputEventProps>
    | ComputedRef<Partial<InputProps & ExtraProps> & InputEventProps>
    | (Partial<InputProps & ExtraProps> & InputEventProps);
}

export type SelectForm<T> = BaseForm<T> & CommonProps & OptionsProps & {
    initValue: any;
    type: Form.Select;
    props?:
    | (() => Partial<ISelectProps & ExtraProps> & SelectEventProps)
    | Ref<Partial<ISelectProps & ExtraProps> & SelectEventProps>
    | ComputedRef<Partial<ISelectProps & ExtraProps> & SelectEventProps>
    | (Partial<ISelectProps & ExtraProps> & SelectEventProps);
}

type CheckProps = {
    border?: boolean;
    size?: 'large' | 'default' | 'small';
};

export type RadioGroupForm<T> = BaseForm<T> & CommonProps & OptionsProps & {
    type: Form.RadioGroup;
    props?:
    | (() => Partial<RadioGroupProps & ExtraProps> & RadioEventProps)
    | Ref<Partial<RadioGroupProps & ExtraProps> & RadioEventProps>
    | ComputedRef<Partial<RadioGroupProps & ExtraProps> & RadioEventProps>
    | (Partial<RadioGroupProps & ExtraProps> & RadioEventProps);
    radioProps?:
    | (() => ExtraProps & CheckProps)
    | Ref<ExtraProps & CheckProps>
    | ComputedRef<ExtraProps & CheckProps>
    | (ExtraProps & CheckProps);
}

export type CheckboxGroupForm<T> = BaseForm<T> & CommonProps & OptionsProps & {
    type: Form.CheckboxGroup;
    props?:
    | (() => Partial<CheckboxGroupProps & ExtraProps> & CheckboxEventProps)
    | Ref<Partial<CheckboxGroupProps & ExtraProps> & CheckboxEventProps>
    | ComputedRef<Partial<CheckboxGroupProps & ExtraProps> & CheckboxEventProps>
    | (Partial<CheckboxGroupProps & ExtraProps> & CheckboxEventProps);
    checkboxProps?:
    | (() => ExtraProps & CheckProps)
    | Ref<ExtraProps & CheckProps>
    | ComputedRef<ExtraProps & CheckProps>
    | (ExtraProps & CheckProps);
}

export type SwitchForm<T> = BaseForm<T> & CommonProps & {
    type: Form.Switch;
    props?:
    | (() => Partial<SwitchProps & ExtraProps> & SwitchEventProps)
    | Ref<Partial<SwitchProps & ExtraProps> & SwitchEventProps>
    | ComputedRef<Partial<SwitchProps & ExtraProps> & SwitchEventProps>
    | (Partial<SwitchProps & ExtraProps> & SwitchEventProps);
}

export type InputNumberForm<T> = BaseForm<T> & CommonProps & {
    type: Form.InputNumber;
    props?:
    | (() => Partial<InputNumberProps & ExtraProps> & InputNumberEventProps)
    | Ref<Partial<InputNumberProps & ExtraProps> & InputNumberEventProps>
    | ComputedRef<Partial<InputNumberProps & ExtraProps> & InputNumberEventProps>
    | (Partial<InputNumberProps & ExtraProps> & InputNumberEventProps);
}

type CustomForm<T> = BaseForm<T> & {
    type: Form.Custom;
    initValue: any;
    props?: any;
}

export type DividerForm = {
    type: Form.Divider;
    title: string;
    props?:
    | (() => Partial<DividerProps & ExtraProps>)
    | Ref<Partial<DividerProps & ExtraProps>>
    | ComputedRef<Partial<DividerProps & ExtraProps>>
    | Partial<DividerProps & ExtraProps>;
    visible?: boolean | (() => boolean) | Ref<boolean> | ComputedRef<boolean>;
}

export type FormFieldItem<T> = InputForm<T> | SelectForm<T> | RadioGroupForm<T> | CheckboxGroupForm<T> | SwitchForm<T> | InputNumberForm<T> | CustomForm<T> | DividerForm;

事件类型

ts
export type InputEventProps = {
    onBlur?: (event: FocusEvent) => void; // 失焦事件
    onFocus?: (event: FocusEvent) => void; // 聚焦事件
    onChange?: (value: string | number) => void; // 值改变事件
    onInput?: (value: string | number) => void; // 输入事件
    onClear?: () => void; // 清空事件
}

export type SelectEventProps = {
    onChange?: (value: any) => void; // 值改变事件
    onVisibleChange?: (visible: boolean) => void; // 下拉框显示隐藏事件
    onRemoveTag?: (tagValue: any) => void; // 移除标签事件
    onClear?: () => void; // 清空事件
    onBlur?: (event: FocusEvent) => void; // 失焦事件
    onFocus?: (event: FocusEvent) => void; // 聚焦事件
}

export type CheckboxEventProps = {
    onChange?: (value: string[] | number[]) => void; // 值改变事件
}

export type RadioEventProps = {
    onChange?: (value: string | number | boolean) => void; // 值改变事件
}

export type SwitchEventProps = {
    onChange?: (val: boolean | string | number) => void; // 值改变事件
}

export type InputNumberEventProps = {
    onChange?: (currentValue: number | undefined, oldValue: number | undefined) => void; // 值改变事件
    onBlur?: (event: FocusEvent) => void; // 失焦事件
    onFocus?: (event: FocusEvent) => void; // 聚焦事件
}

Expose属性

属性名说明类型
instance表格实例Ref<FormInstance>
validate对整个表单的内容进行验证。 接收一个回调函数,或返回 Promise。(callback?: FormValidateCallback) => Promise<void>
resetFields重置该表单项,将其值重置为初始值,并移除校验结果。(props?: Arrayable<FormItemProp> | undefined) => void
clearValidate清理某个字段的表单验证信息。(props?: Arrayable<FormItemProp> | undefined) => void