背景
- 直播中后台绝大部分(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>