formily自定义组件步骤

  1. connect 桥接组件,antd 组件和 formily的桥接
  2. 定义桥接组件的 Resource� 配置,例如 Tree.Resource
    1. template:组件模板
    2. 物料的 json schema
  3. 定义桥接组件的 Behavior� 属性描述,例如 Tree.Behavior

https://github.com/alibaba/designable/discussions/136
https://zhuanlan.zhihu.com/p/431263711
https://www.yuque.com/aspirantzhang/antdprov5/iwibfb

Formily框架中,调用组件时,会自动注入几个属性

  • value
  • onChange对 Form实例对象上的对应 name表单项的 value进行修改
  • dataSource,比如在Select中,就是通过JSON描述的Enum值
  • onBlur,JSON中的default字段改
  • onFocus

渲染时

场景:用于渲染成 jsx时,只用于 JsonSchema解析时
x-component 对应的组件字符串

编辑时

编辑器交互显示

  • Behavior:组件行为的描述
  • Resource:组件资源的描述
  • template:组件预设模板

    Resource

    designable 提供了两个对象来负责不同的功能模块
  1. Resource:配置组件库的小部件 weigets展示
    1. 职责就是用于代码的生成。在生成代码阶段
    2. 设计器中所有涉及到节点修改的地方,其实都是针对 TreeNode 这个虚拟节点树对象进行操作
    3. 在 designable 底层它会被转换为 Formily Schema
  2. Behavior:配置预览组件在 Canvas 中的操作配置
    1. 比如是否可拖拽、可删除、可复制等功能
    2. 用于定义组件的所有可交互的接口,例如控制与限制拖拽生成阶段的容器与层级关系,比如限定某个组件只能拖拽到固定的视图节点

weigets

disignable组件四种展形态
1. 小部件 widget
2. 预览态 Preview
3. 渲染态 RenderComponent
4. 只读态 Readonly

Behavior

以 Rate组件为例拆分组件
从 components目录下,找一个简单的组件为例,来了解 designable组件的组成
image.png

  1. import React from 'react'
  2. import { Rate as AntdRate } from 'antd'
  3. import { createBehavior, createResource } from '@designable/core'
  4. import { DnFC } from '@designable/react'
  5. import { createFieldSchema } from '../Field'
  6. import { AllSchemas } from '../../schemas'
  7. import { AllLocales } from '../../locales'
  8. export const Rate: DnFC<React.ComponentProps<typeof AntdRate>> = AntdRate
  9. Rate.Behavior = createBehavior({
  10. name: 'Rate',
  11. extends: ['Field'],
  12. // @ts-ignore
  13. selector: (node) => node.props['x-component'] === 'Rate',
  14. designerProps: {
  15. propsSchema: createFieldSchema(AllSchemas.Rate),
  16. },
  17. designerLocales: AllLocales.Rate,
  18. })
  19. Rate.Resource = createResource({
  20. // 展示的图标
  21. icon: 'RateSource',
  22. // 预定义的模板,就是拖拽到画布上显示的属性
  23. elements: [
  24. {
  25. componentName: 'Field',
  26. props: {
  27. type: 'number',
  28. title: 'Rate',
  29. 'x-decorator': 'FormItem',
  30. 'x-component': 'Rate',
  31. },
  32. },
  33. ],
  34. })

icon

createResource下的 icon来源
designable/packages/react/src/icons

  • 支持 svg标签
  • 支持 *.png文件 路径引入的
    1. icon: 'RateSource'
    2. icon: <svg></svg>
    3. icon: 'https://img.alicdn.com/imgextra/i1/O1CN01jnfLpK1rFJ4nPj9Pt_!!6000000005601-55-tps-56-56.svg'
    图片 icon样式 image.png
    1. .dn-resource-item-icon {
    2. width: 56px;
    3. height: 40px;
    4. display: flex;
    5. justify-content: center;
    6. align-items: center;
    7. }

自定义 icon

designzble 自定义 icon参考 designable/packages/react/src/containers/Designer.tsx

  1. import { Engine, GlobalRegistry } from '@designable/core'
  2. import * as icons from '../icons'
  3. GlobalRegistry.registerDesignerIcons(icons)

Select 远程数据

Select组件增加一个远程数据源,实现思路

  1. 自己封装一个带请求的 Select
  2. 选择 Select组件,选择
    1. 响应器规则 - 配置响应器
    2. image.png
    3. 选择动作响应,右侧一个 Async Select
    4. 直接在这里写请求逻辑

image.png

formily自定义 Tree组件

桥接 formily

https://www.yuque.com/xjchenhao/development/dhv90n
https://blog.csdn.net/tianxintiandisheng/article/details/124858824

自定义组件的 Resource & Behavior

image.png

  1. import React from 'react'
  2. import { Tree as AntdTree } from 'antd'
  3. import { TreeProps } from 'antd/lib/tree'
  4. import { connect, mapReadPretty, mapProps, ReactFC } from '@formily/react'
  5. import { PreviewText } from '@formily/antd/lib/preview-text'
  6. import { createBehavior, createResource } from '@designable/core'
  7. import { DnFC } from '@designable/react'
  8. import { LoadingOutlined } from '@ant-design/icons'
  9. import { createFieldSchema } from '../Field'
  10. import { AllSchemas } from '../../schemas'
  11. import { AllLocales } from '../../locales'
  12. // 1 桥接组件
  13. export const AntTree: ReactFC<TreeProps<any, any>> = connect(
  14. AntdTree,
  15. mapProps(
  16. {
  17. dataSource: 'treeData',
  18. loading: true,
  19. },
  20. (props: any, field) => {
  21. return {
  22. ...props,
  23. suffixIcon:
  24. field?.['loading'] || field?.['validating'] ? (
  25. <LoadingOutlined />
  26. ) : (
  27. props.suffixIcon
  28. ),
  29. }
  30. }
  31. ),
  32. mapReadPretty(PreviewText.Tree)
  33. )
  34. export const Tree: DnFC<React.ComponentProps<typeof AntdTree>> = AntTree
  35. // 行为
  36. // @ts-ignore
  37. Tree.Behavior = createBehavior({
  38. name: 'Tree',
  39. extends: ['Field'],
  40. selector: (node) => {
  41. // @ts-ignore
  42. return node.props['x-component'] === 'Tree'
  43. },
  44. designerProps: {
  45. // 组件默认属性配置
  46. propsSchema: createFieldSchema(AllSchemas.Tree),
  47. },
  48. designerLocales: AllLocales.Tree,
  49. })
  50. // 资源
  51. // @ts-ignore
  52. Tree.Resource = createResource({
  53. icon: 'https://alifd.alicdn.com/fusion-cool/icons/icon-antd/tree-1.jpg',
  54. elements: [
  55. {
  56. componentName: 'Field',
  57. props: {
  58. type: 'string',
  59. title: 'Tree',
  60. // 'x-decorator': 'FormItem',
  61. 'x-component': 'Tree',
  62. },
  63. },
  64. ],
  65. title: 'Tree组件',
  66. // description?: string | IDesignerMiniLocales
  67. // thumb?: string
  68. // span?: number
  69. // elements?: ITreeNode[]
  70. })