关于前端:可视化搭建-容器组件设计

4次阅读

共计 2637 个字符,预计需要花费 7 分钟才能阅读完成。

可视化搭建会遇到如下三类容器组件:

  1. 简略容器:以 children 包容子组件的容器。
  2. 卡片容器:以 props.header 加上 props.header 等多个插槽包容子组件的容器。
  3. Tab 容器:以 props.tabPanel[x] 等动静数量插槽包容子组件的容器。

画布自身也是一个容器组件,所以可视化搭建离不开容器。

另一方面,咱们应该容许给组件 props 传入 React 组件实例,但组件树是可序列化的 JSON 构造,因而须要一种定义形式,将某些属性转化为 React 组件实例传给组件实例。

容器的定义

任何组件都可能是容器组件,只有它将 props.childrenprops.footer 等任何属性作为 ReactNode 渲染。因而咱们不须要非凡申明组件是否为容器,而仅需将某些组件 Key 申明为 ReactNode 节点。

Children

children 因为太罕用因而独自强调进去,能够只在在组件实例定义 children 属性,它为是一个数组:

import {ComponentInstance} from "designer";

const componentTree: ComponentInstance = {
  componentName: "div",
  children: [
    {componentName: "input",},
  ],
};

对于这个组件,Designer 会将 children 定义的属性了解为组件实例,并真正解析为 React 实例传递给 props.children,因而组件渲染代码能够间接应用 children 渲染:

import {ComponentMeta} from "designer";

const divMeta: ComponentMeta = {
  componentName: "div",
  element: ({children}) => <div>{children}</div>,
};

这种约定的益处是直观天然,组件代码也没有关怀到框架逻辑,自然而然实现了容器性能。

treeLike 构造

只有将任意组件 props 定义为数组模式,并且蕴含 componentName,Designer 就认为应该解析为 ReactNode。

如上面的例子,咱们定义的 div 组件初始化就会渲染一个 input 组件在 props.header 地位:

import {ComponentMeta} from "designer";

const divMeta: ComponentMeta = {
  componentName: "div",
  element: ({header}) => <div>{header}</div>,
  defaultProps: {
    header: [
      {componentName: "input",},
    ],
  },
};

也能够在形容组件树时间接写在对应 props 地位:

import {ComponentInstance} from "designer";

const componentTree: ComponentInstance = {
  componentName: "div",
  props: {
    header: [
      {componentName: "input",},
    ],
  },
};

这种约定的益处是直观的反对了任意 props key 为组件实例,但仍然存在限度,因而 Designer 还须要反对一种用户 100% 掌控的申明式定义:propTypes

PropTypes

在组件元信息 propTypes 属性定义更粗疏的容器插槽地位,比方:

const tabMeta = {
  componentName: "tab",
  propTypes: {
    tabs: [
      {panel: "element",},
    ],
  },
};

那么当组件实例如下定义时:

const componentInstance = {
  componentName: "tab",
  props: {
    tabs: [
      {
        title: "tab1",
        panel: {componentName: "card",},
      },
      {
        title: "tab2",
        panel: {componentName: "text",},
      },
    ],
  },
};

组件拿到的 props.tabs[0].panel 就是一个能够间接渲染的 React 组件实例,因为在 propTypes 定义了 tabs[].panel 门路是一个组件实例。

这样设计须要思考组件树遍历的问题,因为组件实例地位定义在组件元信息上,因而仅靠组件树无奈做遍历(因为遍历父节点时,不联合 componentMeta 就无奈确认哪些 props 地位是子组件实例),这样会带来两个问题:

  1. 遍历组件十分麻烦,极其状况下,如果大量组件是近程注册的三方组件,会导致须要一层层串行近程拉取组件实例,导致遍历过程变慢。
  2. 更极其的场景是,当组件版本升级导致 propTypes 变动,一些本来不是组件实例的地位成为了组件实例,或者反之,此时拉取最新组件元信息读取的 propTypes 可能就是错的。

因为以上两个起因,实现计划应该是将组件元信息定义的 propTypes 拷贝一份到组件实例,这样就能够仅凭组件树本身来遍历组件树了,而且定义在组件树上的 propTypes 肯定对应以后组件树的构造。

总结

咱们通过 children 与 props 上 treeLike 这两个约定,实现了业务根本够用的容器定义能力,仅凭这两个约定就能够实现简直所有容器须要的成果。

propTypes 定义补全了约定拓展性的有余,让 props 任何地位都可能成为组件实例,只须要付出额定定义 propTypes 的代价。

浏览到这,置信你曾经了解到,可视化搭建其实不存在容器组件的概念,因为这个组件之所以是容器,仅仅因为它的某个 prop 属性是组件实例,而它恰好将该属性渲染到某个地位(甚至用 createPortal 挂载到其余 dom 节点),所以它仅仅是一种 prop 属性的体现,因而对容器组件,咱们没有设计一种新 type,而是容许任意地位属性定义为实例。

下一节咱们会介绍为组件元信息增加取数与筛选联动的钩子,让筛选器 + 查问场景能够轻松被实现。

探讨地址是:精读《容器组件设计》· Issue #468 · dt-fe/weekly

如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 – 帮你筛选靠谱的内容。

关注 前端精读微信公众号

<img width=200 src=”https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg”>

版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)

正文完
 0