一、前沿
基于 Ant Design Vue 组件库实现了表单的配置化生成,通过 schema 配置化的方式实现表单的动态渲染、数据绑定和更新等功能,而提交按钮及获取数据逻辑由使用方自行提供。通过 schema
对象来定义表单的结构和属性,modelData
对象存储表单数据。主要组件包括 z-form-generator
、formGeneratorGroup
以及各种具体的表单字段组件(如 field-date
、field-radio
等)。
二、具体实现
1. schema
配置
- 结构定义:
schema
对象包含containers
(表单结构的 JSON 数据)、colNum
(最多展示列数)和isViewType
(表单是否为只读)等属性。containers
中可以包含多个组件配置,每个组件配置又有type
、label
、model
等属性。
javascript">schema: {containers: [],colNum: 2,isViewType: false
}
- 字段配置:不同类型的字段组件(如日期、单选、多选等)根据
schema
中的type
属性来确定使用哪个具体的组件进行渲染。例如,type: 'date'
会使用field-date
组件。
2. 组件渲染
formGeneratorGroup
组件:根据schema
中的type
属性动态渲染不同的表单字段组件。通过getFieldType
方法type
获取组件名称,并使用 JSX 进行渲染。
javascript">// formGeneratorGroup.js
const { getFieldType, field, colNum } = this
const comArr = ['area', 'checkbox', 'date', 'file', 'input', 'radio', 'search', 'select', 'upload', 'modal', 'cascader', 'list']
let isCom = _.includes(comArr, field.type)
const component = isCom ? getFieldType(field) : null
const { type, ...restProps } = field
return (<a-col>{component && <componentschema={restProps}modelData={this.modelData}isViewType={this.isViewType}on-model-updated={this.onModelUpdated}on-error-updated={this.onErrorUpdated}on-schema-updated={this.onSchemaUpdated}/>}</a-col>
)
- 具体字段组件:每个字段组件(如
field-date
、field-radio
等)根据schema
中的属性进行渲染,并处理相应的事件(如onChange
)。
getFieldType ({ type } = {}) {if (!type) {throw new Error('请确认组件类型')}return `Field-${type}`},
3. 组件化设计
采用组件化的设计思想,将不同类型的表单组件封装成独立的组件,如 FieldRadio
、FieldCheckbox
、FieldFile
等。每个组件都接收 schema
和 modelData
作为 props
,通过 render
函数动态渲染表单元素。
// field-radio.vue
export default {name: 'FieldRadio',props: {schema: {type: Object,default: () => ({}),require: true,},modelData: {type: Object,default: () => ({}),},},methods: {changeHandle (e) {this.value = e.target.value},},render () {const { label, model, list, optionName, ...restSchema } = this.schemaconst { keyName: key, valueName: val } = {keyName: 'key',valueName: 'val',...optionName,}return <a-form-model-itemlabel={label}prop={model}><a-radio-groupvalue={this.value}prop={{ ...restSchema }}onChange={this.changeHandle}><a-row>{list && list.map(el =><a-col span={12}><a-radio value={el[key]}>{el[val]}</a-radio></a-col>)}</a-row></a-radio-group></a-form-model-item>},
}
4. 数据绑定与更新
通过 modelData
对象实现表单数据的绑定。在组件中,通过 props
属性将 model
绑定到表单元素上,然后通过 $emit
触发自定义事件,将数据更新传递给父组件。
// field-radio.vue
methods: {changeHandle (e) {this.value = e.target.valuethis.$emit('model-updated', this.schema, this.value)},
}
5. 校验规则初始化
通过 initRules
方法初始化表单的校验规则。根据 schema
中的 required
属性和组件类型,为每个字段添加相应的校验规则。
javascript">// formGenerator.vue
initRules () {const { containers, rules } = this.cloneSchema// 初始化规则校验对象let initRules = { ...rules }// 平铺所有容器的fieldsconst components = containers.reduce((acc, container) => {acc.push(...container.components);return acc;}, []);// 统一处理字段规则components.forEach(field => {const { code, type, required, inputType, regular, errorMessage, precision } = field;// 初始化当前字段的校验规则if (!initRules[code]) initRules[code] = [];// 兼容 required 历史数据if (required) {const requiredRule = type === 'list'? { required: true, message: '该列表不得为空,请为列表新增数据' }: { required: true, message: '该项不得为空', trigger: type === 'date' ? 'change' : 'blur' };initRules[code].unshift(requiredRule);}// 如果是input类型组件,处理其校验规则if (type === 'input') {let ruleItem = initRules[code];// 处理内建的输入框类型校验if (inputType && ['phone', 'intNum', 'number', 'email', 'idCardNo', 'bussNo', 'bankNo'].includes(inputType)) {const { reg, message } = inputType === 'number' ? RulesReg[inputType][idx] : RulesReg[inputType]addValidationRule.call(this, ruleItem, reg, message)}// 处理自定义正则校验if (regular) {const reg = new RegExp(regular);const message = errorMessage;addValidationRule.call(this, ruleItem, reg, message)}initRules[code] = [...ruleItem];}})// 更新规则this.rules = initRules;
}addValidationRule(ruleItem, reg, message) {ruleItem.push({validator: (rule, value, cb) => this.valitaRule(reg, value, cb, message),trigger: 'blur',});
}
三、特点
- 配置化设计:通过
schema
配置化的方式,实现了表单的动态生成和定制,提高了代码的可维护性和可扩展性。 - 组件化开发:将不同类型的表单组件封装成独立的组件(如
field-date
、field-radio
等),提高了代码的复用性和可测试性。 - 动态渲染:根据
schema
中的type
属性动态渲染不同的表单组件,实现了表单的灵活定制。 - 规则校验:支持多种类型的规则校验,包括必填项校验、输入框校验等,确保了用户输入数据的合法性。