Formily高级特性:表单构建器与可视化开发

Formily高级特性:表单构建器与可视化开发

【免费下载链接】formily 📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3 【免费下载链接】formily 项目地址: https://gitcode.com/gh_mirrors/fo/formily

本文详细介绍了Formily生态中的可视化表单设计工具Form Builder及其核心架构设计理念。文章阐述了Form Builder基于Designable框架构建的模块化架构,包括资源组件系统、多视图切换机制、国际化支持、快捷键配置等核心功能。同时深入解析了动态表单与条件渲染的实现原理,包括响应式状态管理、Schema驱动的条件表达式、依赖追踪系统和性能优化策略。

Form Builder:可视化表单设计工具

Form Builder 是 Formily 生态中的可视化表单设计工具,它基于 Designable 框架构建,为开发者提供了直观、高效的拖拽式表单构建体验。通过 Form Builder,开发者可以无需编写大量代码即可快速创建复杂的表单界面,极大提升了开发效率。

核心架构与设计理念

Form Builder 采用模块化架构设计,每个功能组件都可以独立替换和扩展。其核心设计理念是将表单设计器分解为多个可组合的模块:

mermaid

核心组件详解

1. 资源组件系统

Form Builder 提供了丰富的预置组件资源,分为四大类别:

组件类别包含组件功能描述
输入控件Input, Select, Checkbox, Radio, DatePicker 等表单数据输入组件
布局组件FormGrid, FormTab, FormLayout, Card, Space 等表单布局和组织组件
自增组件ArrayCards, ArrayTable动态数组字段组件
显示组件Text只读文本显示组件
2. 多视图切换机制

Form Builder 支持四种不同的视图模式,满足不同场景下的设计需求:

  • DESIGNABLE 视图:可视化拖拽设计界面
  • JSONTREE 视图:JSON Schema 树形结构编辑
  • MARKUP 视图:标记语言代码视图
  • PREVIEW 视图:实时预览效果

配置与自定义

国际化支持

Form Builder 内置多语言支持,可以轻松实现界面国际化:

GlobalRegistry.registerDesignerLocales({
  'zh-CN': {
    sources: {
      Inputs: '输入控件',
      Layouts: '布局组件',
      Arrays: '自增组件',
      Displays: '显示组件',
    },
  },
  'en-US': {
    sources: {
      Inputs: 'Inputs',
      Layouts: 'Layouts',
      Arrays: 'Arrays',
      Displays: 'Displays',
    },
  },
})
快捷键配置

支持自定义快捷键,提升操作效率:

const engine = createDesigner({
  shortcuts: [
    new Shortcut({
      codes: [
        [KeyCode.Meta, KeyCode.S],  // Mac: Command+S
        [KeyCode.Control, KeyCode.S], // Windows: Ctrl+S
      ],
      handler(ctx) {
        saveSchema(ctx.engine)  // 保存Schema
      },
    }),
  ],
  rootComponentName: 'Form',
})

组件注册与使用

在 Form Builder 中注册和使用组件非常简单:

<ComponentTreeWidget
  components={{
    Form,
    Field,
    Input,
    Select,
    // ... 其他组件
    ArrayTable,
    Space,
    FormTab,
    FormCollapse,
    FormGrid,
    FormLayout,
    ObjectContainer,
  }}
/>

属性配置面板

SettingsPanel 提供了详细的组件属性配置功能:

<SettingsPanel title="panels.PropertySettings">
  <SettingsForm uploadAction="https://www.mocky.io/v2/5cc8019d300000980a055e76" />
</SettingsPanel>

数据持久化与导出

Form Builder 支持将设计结果导出为 JSON Schema,便于后端存储和前端渲染:

const saveSchema = (engine: Engine) => {
  const schema = engine.getCurrentTree()
  // 保存到服务器或本地存储
  console.log('Schema saved:', schema)
}

扩展性与自定义

Form Builder 具有极高的扩展性,开发者可以:

  1. 自定义组件:注册新的表单组件
  2. 自定义行为:扩展拖拽、连线等交互行为
  3. 自定义视图:添加新的视图模式
  4. 自定义配置:扩展属性配置面板

典型工作流程

mermaid

Form Builder 通过这种直观的可视化设计方式,让表单开发变得更加高效和愉悦。无论是简单的数据录入表单还是复杂的业务表单,都可以通过拖拽和配置快速完成,大大降低了表单开发的技术门槛。

动态表单与条件渲染的实现原理

Formily 的动态表单与条件渲染能力是其核心特性之一,它通过精妙的响应式设计和 Schema 驱动机制,实现了高度灵活的表单交互体验。这一功能的实现基于以下几个关键技术原理:

响应式状态管理架构

Formily 采用基于观察者模式的响应式状态管理,通过 Field 对象之间的依赖关系建立动态联动机制:

// Field 状态管理核心类结构
class BaseField {
  private _display: FieldDisplayTypes = 'visible'
  private _hidden = false
  private _disabled = false
  private _readOnly = false
  private _required = false
  
  // 响应式状态更新方法
  setDisplay(display: FieldDisplayTypes) {
    if (this._display !== display) {
      this._display = display
      this.notifyObservers('display')
    }
  }
  
  setHidden(hidden: boolean) {
    if (this._hidden !== hidden) {
      this._hidden = hidden
      this.notifyObservers('hidden')
    }
  }
}

Schema 驱动的条件表达式

Formily 通过 JSON Schema 的扩展属性实现条件渲染,主要利用 x-reactionsx-component-props 等扩展属性:

{
  "type": "object",
  "properties": {
    "showAdvanced": {
      "type": "boolean",
      "title": "显示高级选项"
    },
    "advancedOption": {
      "type": "string",
      "title": "高级选项",
      "x-reactions": [
        {
          "dependencies": ["showAdvanced"],
          "fulfill": {
            "state": {
              "visible": "{{$deps[0]}}"
            }
          }
        }
      ]
    }
  }
}

依赖追踪与副作用管理

Formily 建立了一套完整的依赖追踪系统,通过 Graph 类管理字段间的依赖关系:

mermaid

表达式引擎实现

Formily 内置强大的表达式引擎,支持复杂的条件判断和数据转换:

表达式类型语法示例功能描述
值比较{{$value > 10}}字段值与常量比较
依赖值{{$deps[0] === 'show'}}依赖字段值判断
函数调用{{$deps[0].includes('test')}}字符串操作函数
逻辑运算{{$deps[0] && $deps[1]}}逻辑与运算

性能优化策略

为了确保动态表单的高性能,Formily 采用了多项优化措施:

  1. 按需更新机制:只有真正发生变化的字段才会触发重新渲染
  2. 依赖关系缓存:缓存字段间的依赖关系,避免重复计算
  3. 批量更新策略:将多个状态更新合并为单次渲染
  4. 懒计算模式:延迟执行复杂的表达式计算
// 批量更新实现示例
class ReactionScheduler {
  private batchQueue: Array<() => void> = []
  private isBatching = false
  
  schedule(reaction: () => void) {
    if (this.isBatching) {
      this.batchQueue.push(reaction)
    } else {
      this.executeBatch([reaction])
    }
  }
  
  startBatch() {
    this.isBatching = true
  }
  
  endBatch() {
    if (this.batchQueue.length > 0) {
      this.executeBatch(this.batchQueue)
      this.batchQueue = []
    }
    this.isBatching = false
  }
}

条件渲染的生命周期

Formily 的条件渲染遵循严格的生命周期管理,确保状态变更的有序性:

mermaid

复杂场景下的联动实现

对于复杂的业务场景,Formily 支持多层级的条件嵌套和组合:

{
  "type": "object",
  "properties": {
    "userType": {
      "type": "string",
      "enum": ["personal", "enterprise"]
    },
    "companyName": {
      "type": "string",
      "x-reactions": [
        {
          "dependencies": ["userType"],
          "fulfill": {
            "state": {
              "visible": "{{$deps[0] === 'enterprise'}}",
              "required": "{{$deps[0] === 'enterprise'}}"
            }
          }
        }
      ]
    },
    "personalInfo": {
      "type": "object",
      "properties": {
        "age": {
          "type": "number",
          "x-reactions": [
            {
              "dependencies": ["userType"],
              "fulfill": {
                "state": {
                  "visible": "{{$deps[0] === 'personal'}}"
                }
              }
            }
          ]
        }
      }
    }
  }
}

这种基于 Schema 的声明式编程模式,使得复杂的表单逻辑可以通过简洁的 JSON 配置来实现,大大提高了开发效率和代码的可维护性。

复杂布局与嵌套表单的处理方案

Formily 提供了强大的布局系统和嵌套表单处理能力,能够轻松应对各种复杂的业务场景。通过灵活的布局组件和嵌套字段管理,开发者可以构建出结构清晰、功能丰富的表单界面。

网格布局系统

Formily 的网格布局系统基于 CSS Grid 实现,提供了响应式的布局能力。通过 FormGrid 组件,可以轻松实现多列布局、自适应调整和复杂的表单排列。

import { FormGrid } from '@formily/antd'

const ComplexLayoutForm = () => {
  return (
    <FormGrid maxColumns={4} minColumns={2} columnGap={16} rowGap={8}>
      <FormGrid.GridColumn gridSpan={2}>
        <FormItem label="姓名" name="name" required>
          <Input />
        </FormItem>
      </FormGrid.GridColumn>
      <FormGrid.GridColumn gridSpan={2}>
        <FormItem label="年龄" name="age">
          <InputNumber />
        </FormItem>
      </FormGrid.GridColumn>
      <FormGrid.GridColumn gridSpan={4}>
        <FormItem label="详细地址" name="address">
          <Input.TextArea />
        </FormItem>
      </FormGrid.GridColumn>
    </FormGrid>
  )
}

网格布局支持多种配置选项:

配置项类型默认值说明
maxColumnsnumberInfinity最大列数
minColumnsnumber1最小列数
columnGapnumber8列间距
rowGapnumber4行间距
breakpointsnumber[][720, 1280, 1920]响应式断点

嵌套对象字段处理

Formily 通过 ObjectField 组件支持深度嵌套的表单结构,可以处理复杂的对象层级关系。

import { ObjectField } from '@formily/react'

const NestedObjectForm = () => {
  return (
    <Form>
      <Field name="user" component={[ObjectField]}>
        <FormItem label="用户信息">
          <Field name="name" component={[Input]} decorator={[FormItem]} />
          <Field name="age" component={[InputNumber]} decorator={[FormItem]} />
          
          <ObjectField name="address">
            <FormItem label="地址信息">
              <Field name="province" component={[Input]} decorator={[FormItem]} />
              <Field name="city" component={[Input]} decorator={[FormItem]} />
              <Field name="street" component={[Input]} decorator={[FormItem]} />
            </FormItem>
          </ObjectField>
        </FormItem>
      </Field>
    </Form>
  )
}

数组卡片布局

对于动态列表数据,Formily 提供了 ArrayCards 组件来处理可增删的数组字段,支持复杂的嵌套结构。

import { ArrayCards } from '@formily/antd'

const ArrayCardsForm = () => {
  return (
    <Form>
      <ArrayCards name="users">
        {({ index }) => (
          <ArrayCards.Item key={index} title={`用户 ${index + 1}`}>
            <FormGrid maxColumns={2}>
              <FormItem label="姓名" name="name">
                <Input />
              </FormItem>
              <FormItem label="邮箱" name="email">
                <Input />
              </FormItem>
              
              <ObjectField name="profile">
                <FormGrid.GridColumn gridSpan={2}>
                  <FormItem label="个人简介">
                    <Input.TextArea />
                  </FormItem>
                </FormGrid.GridColumn>
              </ObjectField>
            </FormGrid>
          </ArrayCards.Item>
        )}
      </ArrayCards>
    </Form>
  )
}

表单选项卡布局

通过 FormTab 组件可以实现选项卡式的表单布局,将复杂的表单内容分组展示。

import { FormTab } from '@formily/antd'

const TabbedForm = () => {
  return (
    <Form>
      <FormTab>
        <FormTab.TabPane tab="基本信息" key="basic">
          <FormGrid maxColumns={2}>
            <FormItem label="姓名" name="name">
              <Input />
            </FormItem>
            <FormItem label="年龄" name="age">
              <InputNumber />
            </FormItem>
          </FormGrid>
        </FormTab.TabPane>
        
        <FormTab.TabPane tab="联系信息" key="contact">
          <FormItem label="邮箱" name="email">
            <Input />
          </FormItem>
          <FormItem label="电话" name="phone">
            <Input />
          </FormItem>
        </FormTab.TabPane>
        
        <FormTab.TabPane tab="附加信息" key="additional">
          <ObjectField name="additional">
            <FormItem label="备注" name="remark">
              <Input.TextArea />
            </FormItem>
          </ObjectField>
        </FormTab.TabPane>
      </FormTab>
    </Form>
  )
}

响应式布局策略

Formily 的布局系统内置了响应式设计,可以根据屏幕尺寸自动调整布局结构。

mermaid

复杂布局组合示例

下面是一个综合运用多种布局组件的复杂表单示例:

const ComplexNestedForm = () => {
  return (
    <Form layout="vertical">
      <FormTab>
        <FormTab.TabPane tab="用户信息" key="user">
          <FormGrid maxColumns={3} minColumns={1}>
            <FormItem label="用户名" name="username" required>
              <Input />
            </FormItem>
            <FormItem label="密码" name="password" required>
              <Input.Password />
            </FormItem>
            <FormItem label="确认密码" name="confirmPassword" required>
              <Input.Password />
            </FormItem>
          </FormGrid>
        </FormTab.TabPane>

        <FormTab.TabPane tab="个人资料" key="profile">
          <ObjectField name="profile">
            <ArrayCards name="education" title="教育经历">
              {({ index }) => (
                <ArrayCards.Item key={index} title={`教育经历 ${index + 1}`}>
                  <FormGrid maxColumns={2}>
                    <FormItem label="学校名称" name="school">
                      <Input />
                    </FormItem>
                    <FormItem label="专业" name="major">
                      <Input />
                    </FormItem>
                    <FormGrid.GridColumn gridSpan={2}>
                      <FormItem label="时间段">
                        <Space>
                          <FormItem name="startDate" noStyle>
                            <DatePicker placeholder="开始日期" />
                          </FormItem>
                          <FormItem name="endDate" noStyle>
                            <DatePicker placeholder="结束日期" />
                          </FormItem>
                        </Space>
                      </FormItem>
                    </FormGrid.GridColumn>
                  </FormGrid>
                </ArrayCards.Item>
              )}
            </ArrayCards>
          </ObjectField>
        </FormTab.TabPane>
      </FormTab>
    </Form>
  )
}

布局性能优化

Formily 的布局系统经过精心设计,确保在复杂场景下仍能保持良好的性能表现:

  1. 分布式渲染:每个字段独立管理状态,避免整树重渲染
  2. 按需更新:只有变化的字段才会触发更新
  3. 内存优化:使用观察者模式减少不必要的内存占用
  4. 批量处理:对多个字段更新进行批量处理,减少渲染次数

通过合理的布局组件组合和嵌套策略,开发者可以构建出既美观又高效的复杂表单界面,满足各种业务场景的需求。

表单数据持久化与状态管理

Formily作为企业级表单解决方案,在数据持久化和状态管理方面提供了强大而灵活的能力。其核心设计理念基于响应式编程和MVVM架构,为复杂表单场景提供了完整的解决方案。

核心状态管理机制

Formily的状态管理建立在@formily/core包的基础上,通过Form类来管理整个表单的生命周期和数据状态。每个表单实例都包含以下核心状态属性:

状态属性类型描述
valuesobject当前表单值
initialValuesobject初始表单值
modifiedboolean表单是否被修改
validatingboolean表单是否正在验证
submittingboolean表单是否正在提交
patternFormPatternTypes表单模式(可编辑、只读、禁用等)
displayFormDisplayTypes表单显示状态(可见、隐藏等)

数据操作API

Formily提供了丰富的数据操作方法,支持各种复杂的数据操作场景:

1. 值设置方法
// 设置整个表单值
form.setValues(values, strategy?: 'merge' | 'deepMerge' | 'shallowMerge' | 'overwrite')

// 设置指定路径的值
form.setValuesIn(pattern: FormPathPattern, value: any)

// 设置初始值
form.setInitialValues(initialValues, strategy?: 'merge' | 'deepMerge' | 'shallowMerge' | 'overwrite')

// 删除指定路径的值
form.deleteValuesIn(pattern: FormPathPattern)
2. 数据提交与重置
// 提交表单
form.submit<T>(onSubmit?: (values: ValueType) => Promise<T> | void): Promise<T>

// 重置表单
form.reset(pattern: FormPathPattern = '*', options?: IFieldResetOptions)

响应式数据流

Formily采用响应式编程模式,通过@formily/reactive实现数据的自动追踪和更新:

mermaid

数据持久化策略

1. 本地存储集成
import { createForm, onFormValuesChange } from '@formily/core'

const form = createForm({
  effects: () => {
    onFormValuesChange((form) => {
      // 自动保存到localStorage
      localStorage.setItem('form_data', JSON.stringify(form.values))
    })
  }
})

// 页面加载时恢复数据
const savedData = localStorage.getItem('form_data')
if (savedData) {
  form.setValues(JSON.parse(savedData))
}
2. 实时数据同步

对于需要实时同步到后端的场景,可以使用防抖策略:

import { debounce } from 'lodash-es'

const form = createForm({
  effects: () => {
    onFormValuesChange(
      debounce((form) => {
        // 异步保存到后端
        api.saveFormData(form.values).catch(console.error)
      }, 500)
    )
  }
})

状态恢复与版本管理

1. 状态快照
class FormStateManager {
  private snapshots: any[] = []
  private currentIndex = -1
  
  takeSnapshot(form: Form) {
    const snapshot = {
      values: toJS(form.values),
      time: Date.now()
    }
    this.snapshots.push(snapshot)
    this.currentIndex = this.snapshots.length - 1
  }
  
  restoreSnapshot(form: Form, index: number) {
    const snapshot = this.snapshots[index]
    if (snapshot) {
      form.setValues(snapshot.values, 'overwrite')
    }
  }
}
2. 版本控制
interface FormVersion {
  id: string
  timestamp: number
  values: any
  description?: string
}

class FormVersionControl {
  private versions: Map<string, FormVersion> = new Map()
  
  saveVersion(form: Form, description?: string) {
    const version: FormVersion = {
      id: uid(),
      timestamp: Date.now(),
      values: toJS(form.values),
      description
    }
    this.versions.set(version.id, version)
    return version.id
  }
  
  loadVersion(form: Form, versionId: string) {
    const version = this.versions.get(versionId)
    if (version) {
      form.setValues(version.values, 'overwrite')
    }
  }
}

批量操作与性能优化

Formily提供了批量操作API,确保在大数据量下的性能表现:

1. 批量字段操作
// 批量重置字段
await form.reset('arrayField.*', {
  forceClear: true,
  validate: false
})

// 批量设置值
form.setValues({
  'field1': 'value1',
  'field2': 'value2',
  'arrayField.0.name': 'item1'
}, 'merge')
2. 性能优化策略
// 使用批量更新减少渲染次数
import { batch } from '@formily/reactive'

batch(() => {
  form.setValuesIn('field1', 'value1')
  form.setValuesIn('field2', 'value2')
  form.setValuesIn('field3', 'value3')
})

// 延迟验证提升用户体验
form.validate().catch(() => {
  // 忽略验证错误,专注于数据持久化
})

错误处理与数据一致性

1. 事务性操作
async function saveFormWithTransaction(form: Form) {
  try {
    form.setSubmitting(true)
    
    // 开始事务
    const transactionId = await api.beginTransaction()
    
    // 保存数据
    await api.saveFormData(transactionId, form.values)
    
    // 提交事务
    await api.commitTransaction(transactionId)
    
    form.setSubmitting(false)
    return true
  } catch (error) {
    // 回滚事务
    await api.rollbackTransaction(transactionId)
    form.setSubmitting(false)
    throw error
  }
}
2. 数据一致性检查
class DataConsistencyChecker {
  private lastSavedValues: any = null
  
  checkConsistency(form: Form): boolean {
    const currentValues = toJS(form.values)
    
    if (this.lastSavedValues === null) {
      this.lastSavedValues = currentValues
      return true
    }
    
    const isConsistent = deepEqual(currentValues, this.lastSavedValues)
    if (!isConsistent) {
      console.warn('Data inconsistency detected')
    }
    
    return isConsistent
  }
  
  markAsSaved(form: Form) {
    this.lastSavedValues = toJS(form.values)
  }
}

高级持久化模式

1. 增量更新策略
class IncrementalPersistence {
  private lastFullData: any = null
  
  async saveIncremental(form: Form) {
    const currentData = toJS(form.values)
    const changes = this.calculateChanges(this.lastFullData, currentData)
    
    if (changes.length > 0) {
      await api.saveChanges(changes)
      this.lastFullData = currentData
    }
  }
  
  private calculateChanges(previous: any, current: any): ChangeRecord[] {
    // 实现差异计算算法
    return []
  }
}
2. 离线存储支持
class OfflineStorage {
  private db: IDBDatabase | null = null
  
  async init() {
    this.db = await this.openDatabase()
  }
  
  async saveFormData(form: Form) {
    if (!this.db) throw new Error('Database not initialized')
    
    const transaction = this.db.transaction(['forms'], 'readwrite')
    const store = transaction.objectStore('forms')
    
    await store.put({
      id: form.id,
      values: toJS(form.values),
      timestamp: Date.now(),
      synced: false
    })
  }
  
  async syncWithServer() {
    // 将离线数据同步到服务器
  }
}

Formily的数据持久化和状态管理机制为复杂企业级应用提供了坚实的基础,通过合理的架构设计和丰富的API,开发者可以构建出既强大又灵活的表单解决方案。

总结

Formily提供了完整的企业级表单解决方案,通过Form Builder可视化工具极大提升了表单开发效率。其强大的动态表单能力基于精妙的响应式设计和Schema驱动机制,支持复杂的条件渲染和联动逻辑。在布局方面,Formily提供了灵活的网格系统、嵌套对象字段处理和多种布局组件组合,能够应对各种复杂业务场景。数据持久化和状态管理机制则确保了表单数据的一致性和可靠性,支持本地存储、实时同步、版本控制和事务性操作。Formily的整体架构设计既保证了开发效率,又提供了极高的扩展性和性能表现,是构建复杂企业级应用的理想选择。

【免费下载链接】formily 📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3 【免费下载链接】formily 项目地址: https://gitcode.com/gh_mirrors/fo/formily

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值