开发动态表单引擎- Schema 设计篇

背景

设计和开发协议驱动的动态表单引擎的第一步就是设计 JSON 协议,也是最重要的一个环节。表单领域的 Schema设计思路 目前主要分为两种:

  • 基于 JSON Schema 扩展

  • 自定义 Schema

JSON Schema 介绍

具体请看文档: 理解 JSON Schema

注意很多人把自定义的 JSON 协议 混淆为 JSON Schema,这是不准确的,JSON Schema 是一套标准,是用于描述和验证 JSON 数据结构的协议。

举个例子,假设我们要定义一个表示人员信息的 JSON 数据结构,包括姓名、年龄。可以使用以下 JSON Schema 来描述这个数据结构:

JSON 复制代码
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer",
      "minimum": 0
    }
  },
  "required": ["name", "age"]
}

对应的 JSON 可能数据为:

JSON 复制代码
{
  "name:"Jack",
  "age":18
}

可以使用 Ajv 等框架基于JSON Schema 描述 对 JSON 数据进行校验。

那么问题来了,为什么使用JSON Schema作为表单协议?

  • JSON Schema 是现有的国际标准,可降低一定迁移和学习成本,也方便其他人员理解。

  • JSON Schema 是对数据结构进行描述,表单就是为了提交数据,且对嵌套场景友好。

  • JSON Schema 本身就是校验数据的,可对表单校验提供帮助。

使用 JSON Schema

JSON Schema 只能对表单的数据进行描述,不能描述视图,比如字符串是用input还是textera,以及组件的props等都需要进行配置。

目前业内有两种做法:

  • 使用单独 UISchema对视图配置进行描述

  • 扩展 JSON Schema 添加自定义属性

第一种做法的代表就是 react-jsonschema-form,这种做法的好处就是能保证 json schema 的标准化和纯洁,方便迁移和接入。缺点就是两份配置维护起来比较麻烦。

JSON 复制代码
{
  "schema": {
    "type": "object",
    "properties": {
      "string": {
        "title": "字符串",
        "type": "string"
      }
    }
  },
  "uiSchema": {
    "string": {
      "ui:width": "50%"
    }
  }
}

第二种就是就是在 JSON Schema的原有基础上扩展一些自定义属性,代表是阿里的 Formily。它统一以x-*格式来表示扩展属性。这种做法的好处就是维护 Schema 配置比较方便。

JSON 复制代码
{
  "type": "string",
  "title": "字符串",
  "description": "这是一个字符串",
  "x-component": "Input",
  "x-component-props": {
    "placeholder": "请输入"
  }
}

自定义 Schema

这种方式相比 JSON Schema 更灵活简洁。这种平铺的结构,是以UI组件的角度对表单进行表述的,对搭建友好。

JSON 复制代码
[
  {
    "type": "input",
    "model": "key",
    "label": "输入框",
    "defaultValue": "",
    "required": true,
    "description": "描述",
    "props": {}
  }
]

如果是平铺的情况下还好,但如果是嵌套对象或者数组的场景下,这种 Schema 描述起来就没有 JSON Schema 那么清晰了。

总结

基于 JSON Schema 的协议是以数据 的角度对表单进行描述的;而自定义 Schema 是以 UI 的角度对表单进行描述。

两种协议的本质区别就是描述的角度不同,各有利弊。

如果场景简单的情况,没有历史包袱,其实基于 UI 描述的 Schema 就挺好。

但如果考虑到多层嵌套以及复杂联动等场景,感觉基于 JSON Schema 扩展的方式更好一些,这也是 Formily 所采用的方案,我也会采用此方案进行开发动态表单。

目前 Vue 没有特别完善的表单解决方案,虽然 Formily 很优秀也支持 Vue,但感觉还是有些复杂,所以想自己造个轮子,当然主要还是以学习和探索为目的。后面会继续讨论表单引擎的几大问题:

  • 校验

  • 嵌套

  • 布局

  • 联动

参考

developer.aliyun.com/article/883...

juejin.cn/post/686286...

相关推荐
尾善爱看海7 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
weixin_BYSJ19877 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Bs_MoneyMagnet8 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
驳是8 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea8 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持8 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者9 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn9 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
Bs_MoneyMagnet11 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师11 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端