开源一套更好用的表单渲染解决方案 SchemaRender

前言

SchemaRender 是一套 默认简单易用,但又追求 灵活高可定制 的表单渲染解决方案,旨在沉淀解决常见表单案例的渲染库,与相关的通用组件,以提升研发效率。

目前主要包含以下内容:

  • Core: 表单渲染库内核,通过一套简易的 JSON Schema 构建出一套表单,内核主要处理 Schema 协议、渲染器编排、逻辑联动、校验能力等,支持 SSR (Server-Side Rendering)。
  • FormRender: 基于 Core + Antd 封装的开箱即用的表单渲染库。
  • Search:基于 FormRender 封装的开箱即用的条件搜索组件。

下面一起看看它们的功能以及怎么使用的。

Core

bash 复制代码
npm install @schema-render/core-react --save

Core 的特点是「轻量级」且无三方包依赖(避免版本不兼容等问题以及核心库的轻量),资源包大小仅 17.6k, gzip 6.5k

Core 需要组装 itemLayout(表单项布局)renderers(渲染器集合) 两个 API 来实现一个渲染库,然后通过 JSON Schema 驱动渲染出所需的表单,下面是一个极简的示例。

jsx 复制代码
import Core from '@schema-render/core-react'

/**
 * 定义 itemLayout (表单项布局结构),这里是很简化的实现
 */
const VerticalItemLayout = ({ schema, body }) => {
  return (
    <div>
      {/* 展示 Schema 协议标题 */}
      <h3>{schema.title}</h3>

      {/* 展示主要内容 */}
      <div>{body}</div>
    </div>
  )
}

/**
 * 定义渲染器集合
 */
const renderers = {
  // 定义渲染器名称,给协议的 renderType 使用
  InputText: {
    // component 是渲染器其中的一个属性,用于定义渲染内容
    component: ({ schema, value, onChange }) => {
      return (
        <input
          {...schema.renderOptions}
          // 将当前表单的数据即 value 传递给组件
          value={value || ''}
          // 输入框事件,更新当前表单项数据
          onChange={(e) => onChange(e.target.value)}
        />
      )
    },
  },
  // 注册文本域渲染器,同样的规则
  Textarea: {
    component: ({ schema, value, onChange }) => {
      return (
        <textarea
          {...schema.renderOptions}
          value={value}
          onChange={(e) => onChange(e.target.value)}
        />
      )
    },
  },
}

/**
 * 用 JSON Schema 描述表达的样子
 * 1、Schema 协议需要以 renderType 为 Root 开头
 * 2、在同级的 properties 属性下声明有哪些「表单项」,用什么渲染器渲染
 */
const schema = {
  renderType: 'Root',
  properties: {
    // 这一级定义表单项的字段
    title: {
      // 这一级是 Schema 协议的属性
      // 定义表单项的标题
      title: '标题',

      // 定义表单项用什么渲染器渲染
      renderType: 'InputText',

      // 传递给渲染器组件的参数
      renderOptions: {
        maxLength: 10,
        placeholder: '请输入标题,最多10个字符',
      },
    },
    // 第二个表单项,同样的规则
    content: {
      title: '内容',
      renderType: 'Textarea',
    },
  },
}

const Demo = () => {
  return (
    <Core
      // 步骤一:注册表单项布局结构
      itemLayout={VerticalItemLayout}
      // 步骤二:注册 Schema 协议需要用到的渲染器
      renderers={renderers}
      // 步骤三:将 Schema 协议传递给内核渲染
      schema={schema}
    />
  )
}

export default Demo

效果如下:

在线编辑体验:

更详细的文档请查看官网

FormRender

bash 复制代码
npm install @schema-render/form-render-react --save

如果存在高定的需求,可以根据 Core 来进行定制,但是通常情况下,可以使用已经封装好的 FormRender,它内置了布局结构以及常用的表单渲染器集合,这样可以做到【开箱即用】,同时也内置了「提交」、「重置」按钮功能。

FormRender 的渲染器集合是基于 Antd 的组件进行封装的。

下面一起看看 FormRender 是怎么使用的,比起 Core 会省事很多。

jsx 复制代码
import FormRender from '@schema-render/form-render-react'

// 定义 Schema 描述
const schema = {
  renderType: 'Root',
  properties: {
    title: {
      title: '标题',
      renderType: 'InputText',
      // 声明表单项必填
      required: true,
    },
    content: {
      title: '内容',
      renderType: 'Textarea',
      required: true,
    },
  },
}

const Demo = () => {
  return (
    <FormRender
      schema={schema}
      // 接收提交事件
      onSubmit={(formData) => {
        console.log('提交成功 formData:', formData)
      }}
    />
  )
}

export default Demo

效果如下:

在线编辑体验:

当然,如果需要高定同时也想保留 FormRender 的能力,那么也可以基于 FormRender 进行定制,它支持 Core 所有的 API。

bash 复制代码
npm install @schema-render/search-react --save

Search 是基于 FormRender 封装的开箱即用的条件搜索组件,常与表格配合用于后台管理系统数据检索与展示操作。

jsx 复制代码
import Search from '@schema-render/search-react'

// 定义 Schema
const schema = {
  renderType: 'Root',
  properties: {
    supplier_name: {
      title: '供应商名称',
      renderType: 'InputText',
    },
    supplier_code: {
      title: '供应商编码',
      renderType: 'InputText',
    },
    bill_no: {
      title: '单据编号',
      renderType: 'InputText',
    },
    bill_type: {
      title: '单据类型',
      renderType: 'Select',
      renderOptions: {
        options: [
          { label: '采购单', value: 1 },
          { label: '入库单', value: 2 },
          { label: '退货单', value: 3 },
        ],
      },
    },
    bill_date: {
      title: '单据日期',
      renderType: 'DateRangePicker',
    },
    bill_status: {
      title: '单据状态',
      renderType: 'Select',
      renderOptions: {
        options: [
          { label: '已提交', value: 1 },
          { label: '待提交', value: 2 },
          { label: '待审批', value: 3 },
        ],
      },
    },
    operator: {
      title: '制单人',
      renderType: 'InputText',
    },
    goods_name: {
      title: '商品名称',
      renderType: 'InputText',
    },
    goods_code: {
      title: '商品编码',
      renderType: 'InputText',
    },
    goods_category: {
      title: '商品分类',
      renderType: 'Select',
      renderOptions: {
        options: [
          { label: '水果鲜花', value: 1 },
          { label: '海鲜水产', value: 2 },
          { label: '粮油调味', value: 3 },
        ],
      },
    },
  },
}

const Demo = () => {
  // 处理搜索
  const handleSearch = async (searchParams) => {
    // 打印搜索条件
    console.log('searchParams:', searchParams)

    // 如:请求接口
    // await queryData()
  }

  return <Search schema={schema} onSubmit={handleSearch} onReset={handleSearch} />
}

export default Demo

效果如下:

表单项个数会根据容器窗口自适应。

在线编辑体验:

更详细的文档请查看官网及其示例

复杂案例

上面是 SchemaRender 的前戏,下面是复杂的案例实现,都可以在官网找到对应的代码及解释。

FormRender 自由位置布局

Demo 地址:schema-render.js.org/form-render...

FormRender 步骤条

Demo 地址:schema-render.js.org/form-render...

Demo 地址:schema-render.js.org/search-reac...

最后

  • 官方文档(更多示例与 API 详解):schema-render.js.org
  • GitHub 仓库地址:github.com/Barrior/sch...
  • 如果遇到 Bug,或者功能支持,请在仓库 issues 大胆提出 👍,合理的能解决的我都会给你解决~
  • 如果觉得项目对你有帮助,烦请 ⭐️ Star 一下支持作者~
相关推荐
用户7138742290017 小时前
构建现代 Web 应用的令牌安全体系:Refresh Token Rotation、HttpOnly Cookie 与 Grace Period 全解析
前端
2601_9564141417 小时前
2026多账号防关联底层逻辑重构:主流指纹浏览器技术架构与高并发横测
重构·架构
之歆17 小时前
Day21_电商详情页核心技术实战:从LESS预处理到复杂交互实现
开发语言·前端·javascript·css·交互·less
ai产品老杨17 小时前
【架构实战】如何基于 Docker 与边缘计算构建企业级 AI 视频管理平台?打通 GB28181/RTSP 统一接入与异构算力调度,全量源码交付破解集成痛点
人工智能·docker·架构
意图共鸣17 小时前
意图共鸣科技《认知智能白皮书》——认知操作系统(COS):大模型之上的“认知中间件”如何调度边界
人工智能·科技·架构
海鸥两三17 小时前
基于 Vue 3 + 高德地图的网格规划系统实战(有源码)
前端·javascript·vue.js
丷丩17 小时前
MapLibre GL JS第11课:获取鼠标指针坐标
前端·javascript·gis·地图·mapbox·maplibre gl js
段一凡-华北理工大学18 小时前
工业领域的Hadoop架构学习~系列文章02:HDFS架构深度剖析
大数据·人工智能·hadoop·学习·架构·高炉炼铁
代码AI弗森18 小时前
前端周刊第 467 期[特殊字符] 本期精选目录
前端
随便的名字18 小时前
前端路由的底层逻辑:URL 中 # 和 ? 的区别与关系详解
前端