Vue3+ElementPlus 表单组件的封装实例

在系统中,表单作为用户与后端交互的重要传递组件使用频率极高,故对其进行封装是必然的,也是一个编写规范代码的前端程序员必须做的一件事。

在Vue3中封装组件时,能感受到与Vue2有着很大的不同,故作此记录。

form文件夹

Vue3+ElementPlus 表单组件的封装实例_第1张图片

  • FormItem.tsx文件是Typescript中的新特性之一,详细可查阅TS中文文档
  • index.vue是主体文件
  • type.ts表单的规约

FormItem.tsx

import filter from '@/utils/filters'
import {
  ElCheckbox,
  ElCheckboxGroup,
  ElDatePicker,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElSelect,
  ElTimePicker
} from 'element-plus'
import { defineComponent } from 'vue'
// 普通显示
const Span = (form: Record, data: Record) => (
  {data.valueProp ? form[data.valueProp] : (data.filter ? filter(form[data.prop], data.filter) : form[data.prop] || '无')}
)
// 输入框
const Input = (form: Record, data: Record) => (
  
  
)
// 数字输入框
const InputNumber = (form: Record, data: Record) => (
  
)
const setLabelValue = (_item: any, { optionsKey }: any = {}) => {
  return {
    label: optionsKey ? _item[optionsKey.label] : _item.label,
    value: optionsKey ? _item[optionsKey.value] : _item.value,
  }
}
// 选择框
const Select = (form: Record, data: Record) => (
  
    {data.options.map((item: any) => {
      return 
    })}
  
)
// 单选/区间日期
const Date = (form: Record, data: Record) => (
  
)
// 单选/区间时间
const Time = (form: Record, data: Record) => (
  
)
// 单选
const Radio = (form: Record, data: Record) => (
  
    {data.radios.map(
      (item: { label: string | number | boolean; value: any }) => {
        return (
          
            {setLabelValue(item, data.prop).value}
          
        )
      },
    )}
  
)
// 多选
const Checkbox = (form: Record, data: Record) => (
  
    {data.checkboxs.map(
      (item: { label: string | number | boolean; value: any }) => {
        return (
          
            {setLabelValue(item, data.prop).value}
          
        )
      },
    )}
  
)
const setFormItem = (
  form: Record | undefined,
  data: Record,
  editable: Boolean,
) => {
  if (!form) return null
  if (!editable) return Span(form, data)
  switch (data.type) {
    case 'input':
      return Input(form, data)
    case 'textarea':
      return Input(form, data)
    case 'password':
      return Input(form, data)
    case 'inputNumber':
      return InputNumber(form, data)
    case 'select':
      return Select(form, data)
    case 'date':
    case 'daterange':
      return Date(form, data)
    case 'time':
      return Time(form, data)
    case 'radio':
      return Radio(form, data)
    case 'checkbox':
      return Checkbox(form, data)
    default:
      return null
  }
}
export default () =>
  defineComponent({
    props: {
      data: Object,
      formData: Object,
      editable: Boolean,
    },
    setup(props) {
      return () =>
        props.data
          ? setFormItem(props.formData, props.data, props.editable)
          : null
    },
  })

index.vue

type.ts

type itemType =
  | 'input'
  | 'select'
  | 'switch'
  | 'radio'
  | 'date'
  | 'time'
  | 'checkbox'
  | 'daterange'
interface FormProps {
  inline?: Boolean
  labelWidth?: string | number
  labelPosition?: 'left' | 'top' | 'right'
  btn?: object[]
}
interface FormItems {
  type: itemType
  label?: string
  prop: string
  valueProp?: string
  width?: string | number
  span?: number
  filter?: string
}
export class commonForm {
  public data: any
  private rules?: object
  public elRowGutter?: number
  public editable?: boolean
  public formProps?: FormProps
  public formItems: FormItems[]
  public dataArray?:object[]
  constructor({
    data = {},
    rules = {},
    editable = true,
    formProps = {},
    formItems = [],
    elRowGutter = 0,
  }: any) {
    this.data = data
    this.rules = rules
    this.elRowGutter = elRowGutter
    this.editable = editable
    this.formItems = formItems
    this.formProps = formProps
  }
}

在页面中引用

Vue3+ElementPlus 表单组件的封装实例_第2张图片

  • changCarrier.vue是主题页面,用来显示表单
  • userForm.ts是对表单进行渲染的数据项

index.vue


useForm

import { commonForm } from '@/components/common/form/type'
import { reactive } from 'vue'
export default () => {
  const rules = {
    name: [
      { required: true, message: '人员名称', trigger: 'blur' }
    ]
  }
  const form = reactive(
    new commonForm({
      data: [],
      editable: true,
      rules: rules,
      formItems: [
        {
          label: '人员名称',
          type: 'select',
          prop: 'name',
        },
        {
          label: '日期范围',
          type: 'daterange',
          prop: 'queueDate',
          format:'YYYY-MM-DD',
          valueFormat:'YYYY-MM-DD',
          startPlaceholder:'开始时间',
          endPlaceholder:'结束时间',
          span: 6,
        },
        {
          label: '时间段范围',
          type: 'time',
          prop: 'timeSlot',
          format:'HH:mm',
          valueFormat:'HH:mm',
          start:'开始时间',
          end:'结束时间',
          isRange:true,
          span: 6,
        },
        {
          label: '允许排队数量',
          type: 'input',
          prop: 'queueNum',
          span: 6,
        },
        {
          label: '生效类型',
          type: 'select',
          prop: 'isDelay',
          options: [
            {
              label: '当日生效',
              value: 0,
            },
            {
              label: '次日生效',
              value: 1,
            }
          ],
          span: 6,
        },
        {
          label: '生效时间',
          type: 'date',
          prop: 'effectiveTime',
          format:'YYYY-MM-DD',
          valueFormat:'YYYY-MM-DD',
          span: 6,
        },
      ],
    }),
  )
  return form
}

总结

一百个人有一百个编写代码的习惯,其上实现是基于模块化的思想,可能看起来有点累,但是我相信能帮助到你。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

你可能感兴趣的:(Vue3+ElementPlus 表单组件的封装实例)