在系统中,表单作为用户与后端交互的重要传递组件使用频率极高,故对其进行封装是必然的,也是一个编写规范代码的前端程序员必须做的一件事。
在Vue3中封装组件时,能感受到与Vue2有着很大的不同,故作此记录。
form文件夹
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 ( ) // 多选 const Checkbox = (form: Record{setLabelValue(item, data.prop).value} ) }, )}, data: Record ) => ( {data.checkboxs.map( (item: { label: string | number | boolean; value: any }) => { return ( ) const setFormItem = ( form: Record{setLabelValue(item, data.prop).value} ) }, )}| 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 } }
在页面中引用
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 }
总结
一百个人有一百个编写代码的习惯,其上实现是基于模块化的思想,可能看起来有点累,但是我相信能帮助到你。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。