当前位置: 首页 > Web前端 > HTML

可视化构建-容器组件设计

时间:2023-03-28 01:19:48 HTML

可视化构建会遇到以下三种类型的容器组件:简单容器:容纳带子组件的容器。卡片容器:容纳子组件的容器,具有多个插槽,例如props.header加props.header。Tab容器:一个容器,其中包含具有动态数量插槽的子组件,如props.tabPanel[x]。画布本身也是一个容器组件,所以视觉构建离不开容器。另一方面,我们应该允许将React组件实例传递给组件props,但是组件树是一个可序列化的JSON结构,因此需要有一种定义的方式将某些属性转换为React组件实例并将它们传递给组件实例.任何组件都可以是容器组件,只要它能将任何道具(如props.children或props.footer)呈现为ReactNode。因此,我们不需要具体声明组件是否为容器,只需要声明一些组件Key为ReactNode节点即可。children和children单独突出显示,因为它们太常用了。您只能在组件实例中定义children属性,它是一个数组:import{ComponentInstance}from"designer";constcomponentTree:ComponentInstance={componentName:"div",children:[{componentName:"input",},],};对于这个组件,Designer会将children定义的属性理解为组件实例,实际上将其解析为React实例传递给props.children,所以组件渲染代码可以直接使用children进行渲染:import{ComponentMeta}from"designer";constdivMeta:ComponentMeta={componentName:"div",element:({children})=>

{children}
,};这种约定的好处是直观自然,组件代码不关心框架逻辑,自然而然地实现了容器功能。只要treeLike结构将任何组件props定义为数组模式并包含componentName,Designer认为它应该被解析为ReactNode。如下例,我们定义的div组件的初始化会在props.header位置渲染一个input组件:import{ComponentMeta}from"designer";constdivMeta:ComponentMeta={componentName:"div",element:({header})=>
{header}
,defaultProps:{header:[{componentName:"input",},],},};也可以在描述组件树的时候直接写在对应的props位置:import{ComponentInstance}from"designer";constcomponentTree:ComponentInstance={componentName:"div",props:{header:[{componentName:"input",},],},};这种约定的好处是直观地支持任何props键作为组件实例,但是仍然有限制,所以Designer还需要支持一个用户可以100%控制的声明式定义:propTypes。PropTypes在组件元信息propTypes属性中定义了更详细的容器槽位置,例如:then当一个组件实例定义如下:tab2",panel:{componentName:"text",},},]],},};组件获取到的props.tabs[0].panel是一个可以直接渲染的React组件实例,因为tabs[]定义在propTypes中。面板路径是一个组件实例。本次设计需要考虑组件树遍历的问题,因为组件实例位置定义在组件元信息上,所以不能单独使用组件树进行遍历(因为遍历父节点时,无法确认是哪些propspositions是子组件实例,没有结合componentMeta),这会带来两个问题:遍历组件很麻烦。极端情况下,如果大量组件是远程注册的三方组件,会导致需要远程串行逐层拉取组件实例,导致遍历过程变慢。更极端的场景是,当组件版本升级导致propTypes发生变化时,一些原本不是组件实例的位置变成了组件实例,反之亦然,通过拉取最新的组件元信息读取到的propTypes可能是错误的。由于以上两点原因,实现方案应该是将组件元信息定义的propTypes复制到组件实例中,这样组件树就可以只被组件树本身遍历,组件树上定义的propTypes必须对应当前组件树的结构。综上所述,通过props上的children和treeLike这两个约定,我们实现了业务基本够用的容器定义能力。只有这两个约定,才能达到几乎所有容器都需要的效果。propTypes的定义弥补了契约扩展性的不足,让任何位置的props成为一个组件实例,只需要付出额外定义propTypes的代价。看完这里相信你已经明白了,在可视化构建中并不存在容器组件的概念,因为这个组件之所以是容器只是因为它的其中一个prop属性是一个组件实例,而恰好渲染了这个property到某个位置(甚至用createPortal挂载到其他dom节点),所以它只是prop属性的一种体现,所以对于容器组件,我们没有设计新的类型,而是允许将任何位置属性定义为一个实例.下一节我们将引入hooks,为组件元信息添加数据检索和过滤联动,轻松实现过滤+查询的场景。讨论地址为:Jingdu《容器组件设计》·Issue#468·dt-fe/weekly想参与讨论的请戳这里,每周都有新话题,周末或周一发布。前端精读——帮你过滤靠谱的内容。关注前端精读微信公众号版权声明:免费转载-非商业-非衍生保留属性(CreativeCommons3.0License)