Formily学习之路(2)react-ComponentTreeWidget

499 阅读1分钟

本地项目启动成功后,就特别好奇中间区域的数据是如何接收?如何处理?最后又如何回传到别的地方?

入口packages/react/src/widgets/ComponentTreeWidget/index.tsx

export const ComponentTreeWidget: React.FC<IComponentTreeWidgetProps> =
  observer((props: IComponentTreeWidgetProps) => {
    const tree = useTree()
    const prefix = usePrefix('component-tree')
    const designer = useDesigner()
    const dataId = {}
    if (designer && tree) {
      dataId[designer?.props?.nodeIdAttrName] = tree.id
    }
    useEffect(() => {
      GlobalRegistry.registerDesignerBehaviors(props.components)
    }, [])
    return (
      <div
        style={{ ...props.style, ...tree?.props?.style }}
        className={cls(prefix, props.className)}
        {...dataId}
      >
        <DesignerComponentsContext.Provider value={props.components}>
          <TreeNodeWidget node={tree} />
        </DesignerComponentsContext.Provider>
      </div>
    )
  }

props: 接收了一个components!components 接收的大抵就是这样子的数据,避免我们阅读分支太多,我们暂时不去细找它这里如何实现等。我们只需要明白这里是我们的数据来源

image.png

Input.Behavior = createBehavior(
  {
    name: 'Input',
    extends: ['Field'],
    selector: (node) => node.props['x-component'] === 'Input',
    designerProps: {
      propsSchema: createFieldSchema(AllSchemas.Input),
    },
    designerLocales: AllLocales.Input,
  },
  {
    name: 'Input.TextArea',
    extends: ['Field'],
    selector: (node) => node.props['x-component'] === 'Input.TextArea',
    designerProps: {
      propsSchema: createFieldSchema(AllSchemas.Input.TextArea),
    },
    designerLocales: AllLocales.TextArea,
  }
)

Input.Resource = createResource(
  {
    icon: 'InputSource',
    elements: [
      {
        componentName: 'Field',
        props: {
          type: 'string',
          title: 'Input',
          'x-decorator': 'FormItem',
          'x-component': 'Input',
        },
      },
    ],
  },
  {
    icon: 'TextAreaSource',
    elements: [
      {
        componentName: 'Field',
        props: {
          type: 'string',
          title: 'TextArea',
          'x-decorator': 'FormItem',
          'x-component': 'Input.TextArea',
        },
      },
    ],
  }
)

从之前上述代码中 我们可以看到组件最终渲染了一个自定义组件 并且传了node={tree} 这个 值、所以我们就需要关注一下 const tree = useTree() 这个hooks做了什么事情呢

// 这里是最根部的一个useTree 处理逻辑了
/**
* 1、生成treeNode 节点【最主要做的事】
* 2、展示区容器
* 
**/

export const useWorkspace = (id?: string): Workspace => {
  // 生成treeNode===>design
  const designer = useDesigner()

  // 区分工作区【表单、表格...】 默认为Form
  const workspaceId = id || useContext(WorkspaceContext)?.id

  if (workspaceId) {
    // 寻找对应工作展示区域【json,代码,控件】
    return designer.workbench.findWorkspaceById(workspaceId)
  }
  // 默认工作区为标签展示
  if (globalThisPolyfill['__DESIGNABLE_WORKSPACE__'])
    return globalThisPolyfill['__DESIGNABLE_WORKSPACE__']
  
  // 兜底处理 
  return designer.workbench.currentWorkspace
}

const designer = useDesigner() 创建一个表单容器

useEffect(() => { GlobalRegistry.registerDesignerBehaviors(props.components) }, []) 注册

dataId[designer?.props?.nodeIdAttrName] = tree.id id匹配

DesignerComponentsContext组件使用react得createContext

image.png


<DesignerComponentsContext.Provider value={props.components}>
          <TreeNodeWidget node={tree} /> // 节点逻辑
        </DesignerComponentsContext.Provider>