Skip to main content
Version: Next

Dynamic Form Engine

Table of Contents​

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion

Introduction​

DyForm is a dynamic form engine built on Vue 3 and TypeScript, implementing UI rendering driven by JSON Schema. The engine supports real-time data binding, form validation, conditional display, nested fields, and other advanced features through configurable form field definitions. The design philosophy of DyForm is to reduce repetitive code and improve development efficiency through declarative configuration, while maintaining high flexibility and extensibility.

Project Structure​

The core file structure of the DyForm dynamic form engine is as follows:

Chart Source

Section Source

Core Components​

DyForm Main Component​

DyForm is the core component of the entire dynamic form engine, responsible for dynamically rendering form fields based on configuration parameters. This component adopts Vue 3's Composition API design, fully utilizing the advantages of the reactive system.

Key Features:

  • JSON Schema Driven: Dynamically generates form fields via formItemProps configuration array
  • Reactive Data Binding: Automatically handles two-way data binding and state synchronization
  • Built-in Component Mapping: Predefines mapping relationships for various common form components
  • Custom Component Support: Supports extending custom components via customWidgetMap
  • Internationalization Support: Automatically adapts form display to different language environments

Form Configuration Interface​

interface FormItemPropType {
prop?: string | Ref<string>
label?: String | Ref<string>
rules?: any[] | Ref<any[]>
disabled?: boolean | Ref<boolean>
placeholder?: string | Ref<string>
type?: string | Ref<string>
width?: string | Ref<string>
el?: string | Component | DefineComponent | Ref<string>
options?: OptionItemType[] | any[] | Ref<any>
isTitle?: boolean
title?: string | Component
[key: string]: any | Ref<string>
}

Section Source

Architecture Overview​

DyForm adopts a layered architecture design, forming a clear hierarchical structure from underlying components to upper-layer applications:

Chart Source

Detailed Component Analysis​

Component Mapping Mechanism​

DyForm implements a flexible component mapping mechanism through formItemElementMap:

const formItemElementMap: Record<string, any> = markRaw({
input: DyInput,
inputNumber: ElInputNumber,
select: Select,
selectInput: SelectInput,
flow: RelationFlowDialog,
variable: Variable,
textareaFlow: TextareaFlow,
switch: (props: PropType<any>, { attrs }: SetupContext) => {
return <el-switch {...attrs} />
},
})

This design allows developers to:

  • Rapidly Extend: Add new form components by modifying the mapping table
  • Component Reuse: Unify the usage of all form components
  • Type Safety: Ensure component type correctness through TypeScript

Dynamic Form Rendering Flow​

Chart Source

Conditional Display and Nested Fields​

DyForm supports complex conditional display logic and nested field structures:

const isHide = has(item.isHide, 'value')
? item.isHide?.value
: item.isHide
return Component && !isHide ? (
<el-form-item
label={itemProps.label}
prop={itemProps.prop}
rules={itemProps.rules}
key={itemProps.prop + index}
>
<Component
modelValue={currentWidgetModel.value(itemProps.prop)}
onUpdate:modelValue={(val: string | number) =>
onUpdateModelValue(val, itemProps.prop)
}
/>
</el-form-item>
) : null

Section Source

Custom Component Extension​

DyForm provides powerful capabilities for extending custom components:

const customWidgetMap = {
inputNumber: ElInputNumber,
flowItemKey: FlowContextDialog,
condition: (props: any, { attrs }: SetupContext) => (
<ConditionDialog
formItemProps={conditionFormItemProps.value}
conditionOptions={conditionOptions.value}
onConditionChange={onConditionChange}
onUpdateFormData={onUpdateFormData}
getCondition={getCondition}
v-model:formData={formData.value.Condition}
{...props}
{...attrs}
/>
),
}

This design enables DyForm to adapt to various complex business scenarios, from simple input boxes to complex condition selectors.

Section Source

Internationalization Support​

DyForm has built-in robust internationalization support mechanisms:

const checkZh = (lang: string) => {
const languageStr = lang.toLowerCase()
if (languageStr.includes('zh')) return true
if (languageStr.includes('original')) return true
return false
}

const onLanguageChange = () => {
Language.useChange((language: any) => {
isZh.value = checkZh(language.lang)
})
}

Section Source

Dependency Analysis​

The dependencies of DyForm reflect a good modular design:

Chart Source

Section Source

Performance Considerations​

Reactivity Optimization​

DyForm employs multiple performance optimization strategies:

  1. Computed Caching: Uses computed properties to cache calculation results
  2. markRaw Optimization: Uses markRaw for static objects to avoid unnecessary reactive tracking
  3. Lazy Initialization: Initializes form data and configuration on demand
const currentWidgetModel = computed(() => {
return (path: string) => {
if (path.includes('.')) {
const args = path.split('.')
return get(form.value, args)
}
return get(form.value, path)
}
})

Memory Management​

  • Event Cleanup: Automatically cleans up event listeners when components are unmounted
  • Reference Management: Reasonably uses ref and reactive to avoid memory leaks
  • Component Destruction: Timely destroys unneeded component instances

Troubleshooting Guide​

Common Issues and Solutions​

  1. Form Validation Not Working

    • Check if rules configuration is correct
    • Confirm trigger event settings
    • Verify data type matching
  2. Custom Component Not Rendering

    • Confirm customWidgetMap configuration
    • Check component import paths
    • Verify component registration method
  3. Data Binding Anomalies

    • Check prop name consistency
    • Confirm v-model binding syntax
    • Verify data type conversion

Debugging Tips​

  • Use Vue DevTools to monitor component state
  • Enable strict mode to check data flow
  • Use console.log to track data changes

Section Source

Conclusion​

The DyForm dynamic form engine is a powerful and elegantly designed form solution. Through its JSON Schema-driven approach, it achieves high flexibility and extensibility. This engine not only simplifies the form development process but also provides rich features, including conditional display, nested fields, and custom components.

Key Advantages:

  • Configuration Driven: Rapidly generate complex forms via JSON configuration
  • Type Safety: Complete TypeScript support ensures development quality
  • Performance Optimization: Reasonable reactive design and caching mechanisms
  • Easy Extension: Clear architecture facilitates feature extension and customization
  • Internationalization Support: Built-in multi-language adaptation capabilities

DyForm provides an excellent solution for form development in modern Web applications, especially suitable for scenarios requiring frequent form structure adjustments or multi-language support.