weixin_39998273
weixin_39998273
2021-01-12 19:05

写几点小建议

废话不多说,直接开门见山

Renderer 按需加载 src/renderers

内置的 Renderer 的有几十上百个,但是可能实际项目用到的只有一小部分,按需加载可以让项目更轻量,使用场景也更广泛,renderer 可以考虑单独发版。

更完备的 Component 库 src/components

相比较一些完整的 UI 框架,现在这套内置的 components 相对简陋,以至于在自定义稍复杂的 renderer 时,需要引用第三方 UI,这样的话,样式没办法简单的统一起来。另外,现在内置的 component 在细节设计上美感不足,是否有考虑直接使用成熟的第三方 UI 来适配 renderer 呢?或者在 renderer 适配 component 时做的更灵活一点,除了更换主题样式以外,还开放适配第三方 UI,比如 antd、material-ui 等等。

注:第三方适配不是说 register renderer 的意思,而是允许从底层更换组件体系,不只是样式层面的覆盖或修改。

文档&例子呈现和维护

配置化的文档,比较喜欢类似 echarts 的这种书写和呈现风格。用 Markdown 来写,最终会将 Markdown 转为一系列 json 文件,文档页面呈现时,从 json 里读取。

  • https://github.com/apache/incubator-echarts-doc
  • https://echarts.apache.org/zh/option.html#title

amis 也可以借鉴这类思路,把书写文档、例子、生成 json schema、生成页面等等统一起来。

https://houtai.baidu.com/v2/schemas/page.json

除了现在 docs 手写的文档,现在这套 json schema 协议也非常赞,除了起到文档作用,也可以用于校验配置,编写时提示,或者用于生成 IDE Helper 都不错,非常利于提高配置效率,相比较别扭的可视化工具,或者去网站上找例子,复制配置,简单有效的 IDE Helper 会更利于平时开发体验。

还有,是否可以把 json schema 的部分开源出来? 现在 json schema 好像稍微滞后,而且还有些错误,描述也比较简陋,example 也没有 ref 进来。开源出来,有不足或者错误的时候,大家可以一起 PR。

这段时间在使用 amis 时,编写了一套 PHP 端写配置的思路,结合 Json Schema 转 Renderer PropTypes,生成 PHP Doc ,写配置就有 IDE Helper 了,开发效率大大提升,还可以生成 TypeScript 的,可以用于前端类型提示,但是受限于 json schema 的内容丰富程度,有些细节做不了,所以非常希望能够更及时的更新和同步 json schema,如果内置到 renderers 里就更好了。不一定直接用 json 来编写,也可以用 yaml 或其他更便捷的方式。

测试用例

感觉这个部分的细节比较容易被人忽视,一个没有完整测试的框架,总感觉缺了些什么,用起来也有些顾虑。可以从几个部分来讲述:

components 部分倾向于独立出来(这里的独立是从项目里完全独立出来的意思),对于大众开发来说,可能更倾向于用现成第三方 UI 适配,至少允许第三方适配,比如上面提到的 antd 或 material-ui。使用第三方那就不需要单独测试 component 了,只需要在 component2renderer 核心部分加上一些测试。

renderers 也是可以独立发版的,测试也独立,还可以把 json schema 结合进来做配置校验。感觉会是个比较强壮的思路。

鸣谢

一直以来,特别热衷于用配置的方式开发,自己也写过 & 用过类似框架,amis 是最对胃口的,而且非常接地气。非常感谢 amis,大大的提升了开发效率。无论 amis 是否是阉割版,能开源就已经很受益了,这段时间也在阅读和学习源码,以上是我这阵子的使用感受和建议,希望可以深入讨论一下。

amis 到现在才 2.8k 的 stars,增长的也比较缓慢,希望未来可以把细节做的更好,stars 再翻几番。

该提问来源于开源项目:baidu/amis

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

5条回答

  • weixin_39569894 weixin_39569894 3月前

    内置的 Renderer 的有几十上百个,但是可能实际项目用到的只有一小部分,按需加载可以让项目更轻量,使用场景也更广泛,renderer 可以考虑单独发版。

    关于这块,我的想法是,把体积比较大的比如 monaco-editor, rich-text 等采用异步 require 去加载,然后编译工具自行取拆包。至于其他零碎的组件,体积不是那么大的,让用户自己去编写个入口文件如:https://github.com/baidu/amis/blob/master/src/index.tsx 去定制,除此之外没有更好的方案了,不知楼主有更好的建议没有。

    是否可以把 json schema 的部分开源出来?

    我会把这个列入计划

    更完备的 Component 库 src/components

    Renderer 里面其实我一直都想拆成 component 和 renderer, 这个后面会慢慢拆。

    点赞 评论 复制链接分享
  • weixin_39998273 weixin_39998273 3月前

    现在的 renderer 有点重,不大改的话,按需加载比较方便的办法还是自己单独打包。异步 require 能解决部分 renderer 问题。我自己的话,是直接源码接入项目,然后再各种魔改 😅

    比较建议从底层把 component 和 renderer 完全解耦,然后重新设计 renderer,让用户可以自己选择注册或加载哪些 renderer,register renderer 的设计也可以更简单方面一点(现在自定义的成本有点高)

    其实 createElement 也是一种配置化书写风格

    js
    React.createElement(
      type, // Component
      [props], // 配置
      [...children] // 子节点
    )
    

    createElement 出发,renderer schema 起到的主要作用是将参数按一定规则映射到组件上(schema2props),如:

    js
    import { Input } from 'antd';
    
    // amis 里 input 是 form 组件,也是一种 renderer:
    
    registerRenderer('text', {
      Component: Input,
      defaultProps: { // 默认值
        type: 'text', // email, url....
      },
      omit: ['type'], // 排除掉不需要处理的 props
      propAliases: { // 给参数定义别名
        type: 'inputType', // 原 type 与 renderer 有冲突,改为 inputType
      },
      // ...还可以加一些其他的补充
    })
    

    上面思路来说,很多 Component 都可以比较简单注入进来了,再举例个复杂点的:

    js
    import { Table } from 'antd';
    
    registerRenderer('table', {
      Component: Table,
      propTypes: {
        dataSource: [
          {
            type: 'array'
          },
          {
            type: 'jsonpath',
            path: '$.items', // 感觉用 jsonpath 来对应 api 数据比较有意思
          }
        ],
      },
    });
    
    render({
      type: 'table',
      api: '/api/table',
    })
    

    对接到组件过程中需要一些 schema2props 转化,propTypes 里可以配置上相关转化,propType 可能有:

    • raw:原始的
    • JSX Element:直接 JSX
    • function
    • tpl:模板
    • html:纯 HTML
    • Renderer:某个 prop 直接对接 Renderer
    • Renderer[]:某个 prop 直接对接 Renderer[] 数组
    • api
    • others

    以上,大部分现成的 ui 组件都能 register 进来,如果参数不一致还可以适配的话,要结合 propAliases 做一些处理。

    然后是两个超复杂的场景 table 和 form,这俩也是可以脱离 UI 设计(还没想清楚 🤔)。

    最后,除了上文提到的全局 registerRenderer,还可以类似这样按需加载:

    js
    render(schema, {
      renderers, // 按需加载
    })
    
    点赞 评论 复制链接分享
  • weixin_39569894 weixin_39569894 3月前

    目前的设计 schema 的 type 和 渲染器不是一一对应的,所以amis里面的叫 test, 需要添加些 上下文。你这里面的 registerRenderer 可以直接接入现有一些 ui 库的 idea 很不错。

    点赞 评论 复制链接分享
  • weixin_39825105 weixin_39825105 3月前

    学芝大佬, monorepo 🚀

    点赞 评论 复制链接分享
  • weixin_39849894 weixin_39849894 3月前

    +1

    强烈希望支持jsx,能有一个对接类似antd的ui方案,或者说提供出来接口也行。。

    点赞 评论 复制链接分享