头图

前言

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

目前主要包含以下内容:

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

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

Core

npm install @schema-render/core-react --save

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

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

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

效果如下:

CoreDemo-sg.png

在线编辑体验:Edit core-demo

更详细的文档请查看官网

FormRender

npm install @schema-render/form-render-react --save

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

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

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

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

效果如下:

FormRenderDemo-sg.png

在线编辑体验:Edit form-render

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

Search

npm install @schema-render/search-react --save

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

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

效果如下:

search-demo-sg.png

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

在线编辑体验:Edit form-render

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

复杂案例

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

FormRender 自由位置布局

Demo 地址:https://schema-render.js.org/form-render-react/850-position

free-position-sg.png

FormRender 步骤条

Demo 地址:https://schema-render.js.org/form-render-react/851-steps

steps-sg.png

Search 分类标题

Demo 地址:https://schema-render.js.org/search-react/850-category-title

category-sg.png

最后


Barrior
598 声望61 粉丝

开源项目 JParticles 与 SchemaRender 作者