如何设计一个表单Schema

727 阅读3分钟

设计一个表单Schema需要综合考虑字段定义、布局结构、验证规则、数据绑定以及动态行为。以下是详细的设计思路和实现方案:


1. Schema结构设计

表单Schema的核心结构应包含以下部分:

根节点(Form配置)

  • 表单全局属性:标题、布局方式、数据模型、提交配置等。
{
  "type": "Form",
  "props": {
    "layout": "vertical",  // 布局类型(horizontal/vertical)
    "labelCol": { "span": 6 },  // 标签布局
    "wrapperCol": { "span": 18 }, 
    "initialValues": { "name": "张三" },  // 初始数据
    "submit": {
      "api": "/api/submit",  // 提交接口
      "method": "POST", 
      "successMessage": "提交成功"
    }
  },
  "children": [ ... ]  // 表单项列表
}

表单项(Form Items)

每个表单项需定义类型、标识符、标签、校验规则等:

{
  "type": "Input",
  "name": "username",  // 对应数据模型的字段名
  "label": "用户名",
  "placeholder": "请输入",
  "required": true,
  "rules": [
    { "type": "minLength", "value": 4, "message": "至少4位" },
    { "type": "regex", "pattern": "^\\w+$", "message": "仅允许字母数字" }
  ],
  "visibleIf": "!isAdmin"  // 条件渲染(依赖其他字段)
}

布局容器

支持嵌套布局(如Grid、Tabs、Card):

{
  "type": "Grid",
  "props": { "columns": 2 },  // 两列布局
  "children": [
    { "type": "Input", "name": "name", "label": "姓名" },
    { "type": "Select", "name": "gender", "label": "性别" }
  ]
}

2. 关键设计点

(1) 数据绑定与双向更新

  • 数据模型映射:每个表单项的name属性对应数据对象的键,例如:
    // Schema中的字段:
    { "type": "Input", "name": "email" }
    
    // 对应数据对象:
    const formData = { email: "user@example.com" };
    
  • 更新机制:通过onChange事件将输入值同步到数据模型。

(2) 动态校验规则

  • 声明式规则:通过rules数组定义校验逻辑,支持组合规则:
    "rules": [
      { "type": "required", "message": "必填" },
      { 
        "type": "custom", 
        "validator": "checkEmailFormat",  // 前端自定义函数
        "message": "邮箱格式错误"
      }
    ]
    
  • 异步校验:支持调用后端接口验证:
    { 
      "type": "async", 
      "api": "/api/check-username", 
      "message": "用户名已存在" 
    }
    

(3) 条件渲染与联动

  • 字段显隐控制:通过visibleIfhiddenIf实现动态显示:
    {
      "type": "Input",
      "name": "company",
      "visibleIf": "userType === 'enterprise'"
    }
    
  • 动态选项:下拉框选项依赖其他字段值:
    {
      "type": "Select",
      "name": "city",
      "options": {
        "source": "api", 
        "url": "/api/cities?province={{province}}"  // 动态参数
      }
    }
    

(4) 复杂布局支持

  • 嵌套容器:支持Grid、Tabs、Collapse等布局组件:
    {
      "type": "Tabs",
      "children": [
        {
          "tab": "基本信息",
          "children": [ ... ]
        },
        {
          "tab": "高级设置",
          "children": [ ... ]
        }
      ]
    }
    

(5) 扩展性与自定义组件

  • 自定义组件注册:允许开发者扩展表单组件库:
    // 注册一个自定义评分组件
    formSchema.registerComponent('Rating', RatingComponent);
    
  • 插槽机制:在特定位置插入自定义内容(如帮助文本):
    {
      "type": "Input",
      "name": "password",
      "extra": {
        "type": "Text",
        "content": "至少包含大小写字母和数字"
      }
    }
    

3. 完整示例

{
  "type": "Form",
  "props": {
    "layout": "vertical",
    "submit": { "api": "/api/submit" }
  },
  "children": [
    {
      "type": "Grid",
      "props": { "columns": 2 },
      "children": [
        {
          "type": "Input",
          "name": "firstName",
          "label": "名",
          "required": true
        },
        {
          "type": "Input",
          "name": "lastName",
          "label": "姓",
          "required": true
        }
      ]
    },
    {
      "type": "Select",
      "name": "country",
      "label": "国家",
      "options": ["中国", "美国", "日本"]
    },
    {
      "type": "Button",
      "text": "提交",
      "action": "submit"
    }
  ]
}

4. 技术实现

(1) 组件解析器

递归遍历Schema,根据type映射到真实组件:

const FormRenderer = ({ schema }) => {
  const Component = componentsMap[schema.type];
  return (
    <Component {...schema.props}>
      {schema.children?.map((child) => (
        <FormRenderer key={child.name} schema={child} />
      ))}
    </Component>
  );
};

(2) 校验引擎

const validate = (schema, data) => {
  const errors = {};
  schema.children.forEach((item) => {
    item.rules?.forEach((rule) => {
      if (rule.type === 'required' && !data[item.name]) {
        errors[item.name] = rule.message;
      }
      // 其他规则校验...
    });
  });
  return errors;
};

5. 设计权衡

  • 性能优化:避免深层嵌套导致渲染卡顿(如虚拟滚动)。
  • 灵活性:通过插槽和自定义组件满足复杂需求。
  • 开发体验:提供Schema可视化生成工具和调试面板。

总结

设计表单Schema的核心在于解耦UI与逻辑,通过JSON配置动态生成表单。重点需关注:

  1. 结构清晰:明确表单、字段、布局的分层关系。
  2. 扩展能力:支持自定义组件、校验规则和动态行为。
  3. 数据驱动:确保表单数据与UI状态实时同步。