背景
- 直播中后台绝大部分(90%)的页面使用 schema form 搭建
- schema form 虽然带来了效率的提升,但由于只支持 json,无法自定义地实现一些定制化的需求
痛点
- json 自身的局限性,导致框架不满足需求时,只能被动等待框架支持该功能
- 无法利用 React jsx 一些方便的特性,无法侵入到组件内部去动态修改一些逻辑
- 无法自由自在地进行布局,目前 schema form 只有从上到下的展示
- 有时候封装一个自定义组件只是为了一个特殊的展示
目标
- 使用 jsx 的方式支持 json 所有已有的功能点,同时尽可能不改变用户已有的认知
- 最大化地满足用户定制化的需求,使得用 jsx 的写法能替代大部分(70%)使用自定义组件的场景
- 在保证自由度的需求上,尽可能简化写法,方便用户的开发
特性
- 实现 jsx 功能
- 提供 json 到 jsx 的一键转化功能
- 提供布局组件
使用方式
原有的使用方式是:
| 1 | const schema = [ | 
转化为 jsx 之后的写法为:
| 1 | const listerners = useFormListeners(() => { | 
主要做了以下优化:
-   尽可能采用简写的形式,比如 ui: { label: '' }直接简写为label字段,同时props中的参数也可以直接透传,比如placeholder
-   更符合 jsx 编写的习惯,可以把 type对应的组件,放入children中,也可以直接作为type传递
-   增加了 Row、Col等布局组件,也可以直接自己写div传入希望的样式,或者加入其它展示元素
XTable 也做了相应优化:
| 1 | <XTable> | 
| 1 | export default () => { | 
进展
- 本地 demo 预研,进行中
XTableJSX初版方案
2021年11月01日
   <ConfigProvider locale={zh_CN}>
      <div style={{ padding: "20px" }}>
        <XTable
          ref={ref}
          onSearch={(core) => console.log("onSearch", core)}
          request={API.list}
        >
          <Row>
            <Col span={20}>
              {/* 检索区域 */}
              <SearchForm
                values={{
                  input: "我是默认值",
                }}
                buttons={(action) => [
                  <Button type="primary" onClick={action.search}>
                    搜索
                  </Button>,
                  <Button onClick={action.reset}>重置</Button>,
                  <Button onClick={action.empty}>清空</Button>,
                ]}
              >
                <XFormItem name="input" type="Input" label="测试" />
                <XFormItem name="input2" type="Input" label="测试2" />
              </SearchForm>
            </Col>
            <Col span={4}>
              <Toolbar>
                <Action
                  type="create"
                  title="新增"
                  buttonProps={{
                    type: "primary",
                  }}
                  api={API.add}
                >
                  <XFormItem name="name" type="Input" label="名字" />
                </Action>
              </Toolbar>
            </Col>
          </Row>
          <ColumnRender
            columns={[
              {
                key: "name",
                title: "名字",
                sortable: true,
              },
              // TODO: 序号列
              // {
              //   key: "index",
              //   type: ({ pageSize, pageIndex, rowIndex }: any) => (
              //     <span>{(pageIndex - 1) * pageSize + rowIndex}</span>
              //   ),
              //   title: "序号",
              // },
              {
                key: "time",
                title: "时间",
                type: "Datetime",
                sortable: true,
              },
              {
                key: "type",
                title: "类型",
                type: "Enum",
                props: {
                  options: [
                    { name: "水果", value: "1" },
                    { name: "蔬菜", value: "2" },
                  ],
                },
              },
              {
                key: "image",
                title: "图片",
                type: "Image",
              },
              {
                key: "format",
                title: "格式",
                type: "Format",
                props: {
                  format: (data: any) => data.value * 100,
                },
              },
              {
                key: "audio",
                title: "音频",
                type: "Audio",
                ui: {
                  width: 300,
                },
              },
              {
                key: "video",
                title: "视频",
                type: "Video",
                ui: {
                  width: 300,
                },
              },
              {
                title: "测试",
                key: "test",
                type: ({ value }: any) => {
                  return <span>{value?.a}</span>;
                },
              },
              {
                title: "操作",
                type: ({ record }: any) => {
                  return (
                    <>
                      <Action
                        type="edit"
                        title="编辑"
                        api={API.update}
                        record={record}
                        buttonProps={{
                          type: "primary",
                        }}
                      >
                        <XFormItem name="name" type="Input" label="名字" />
                      </Action>
                      <Action
                        type="delete"
                        title="删除"
                        api={API.delete}
                        popConfirm={{
                          title: "确认删除", // 此处不配置则默认使用外层title
                          okText: "确定",
                          cancelText: "取消",
                        }}
                        record={record}
                        buttonProps={{
                          type: "danger",
                        }}
                      ></Action>
                      <Button onClick={() => console.log(record)}>
                        自定义按钮
                      </Button>
                    </>
                  );
                },
              },
            ]}
          ></ColumnRender>
        </XTable>
      </div>
    </ConfigProvider>