ComponentLoader 与动态组件实例详解

目录
  • 引言
  • 按组件 ID 加载
  • 按组件树路径加载
  • 动态组件
  • 总结

引言

组件通过 <Canvas /> 渲染在画布上,内容完全由组件树 componentTree 驱动,但也有一些情况我们需要把某个组件实例渲染到组件树之外,比如全屏、置顶等场景,甚至有些时候我们要渲染一个不在组件树中的临时组件,却要拥有一系列画布能力。

为了让组件渲染更灵活,我们暴露出 <ComponentLoader> API:

import { createDesigner } from 'designer'
const { Designer, Canvas, ComponentLoader } = createDesigner()
const App = () => {
  return (
    <Designer componentTree={/** ... */}>
      <Canvas />
      {/** 任意位置,甚至 Canvas 的组件实例内使用 ComponentLoader 加载任意组件 */}
      <ComponentLoader />
    </Designer>
  )
}

组件加载器有三种用法:按组件 ID 加载、按组件树路径加载、动态组件,下面分别介绍。

按组件 ID 加载

将组件树上的某个组件渲染到任何地方,即一个组件实例渲染到 N 个地方,实例级别信息共享,渲染为 N 份:

<ComponentLoader componentId="input1" />

如上例子,将组件 ID 为 input1 的组件渲染到目标位置。

甚至可以在组件内套组件,比如我们定义一个容器组件,内置渲染 ID 为 input1 的子组件:

const container: ComponentMeta = {
  componentName: 'container',
  // 组件 props 会自动注入 ComponentLoader
  element: ({ ComponentLoader, children }) => {
    return (
      <div>
        <ComponentLoader componentId="input1" />
        {children}
      </div>
    )
  }
}

当该组件 ID 在组件树中被移除时,<ComponentLoader componentId="input1" /> 返回 null

按组件树路径加载

如果组件在组件树上没有 ID,或者你希望固定渲染某个位置的组件,而无论组件树如何变化,那么就可以采用按组件树路径的加载模式,将 componentId 替换为 treePath 即可:

<ComponentLoader treePath="children.0" />

如上例子,渲染的是 componentTree 根节点 children.0 位置的子组件,同样,但组件不存在时返回 null

动态组件

如果要渲染一个不存在于组件树的组件实例,还可以这么用 <ComponentLoader />:

<ComponentLoader standalone componentName="card" />

即添加 standalone 表示它为一个 “孤立” 组件,即不存在于组件树的组件,以及 componentName 指定组件名。

之所以不需要指定 componentId,是因为每个 ComponentLoader 此时都是一个唯一的实例,在 designer 内部会自动分配一个固定的组件 ID。

这么设计非常灵活,但实现起来难度是有一些,主要注意两点:

  • 动态组件不存在于组件树,但我们之前设计在组件元信息的所有功能都要可以响应,这就要求框架代码不能依赖组件树产生作用,而是将所有组件独立存储计算,包括组件树上的,以及动态组件。
  • 性能,独立组件加载器之间的执行并无关联,因为框架本身为响应式,为了防止频繁刷新或频繁计算需要设计一套自动批处理机制,类似 React 自动 batch 的实现。

对于动态组件,我们还可以传递更多参数:

<ComponentLoader standalone componentName="chart" props={{ color: 'red' }}>
  <button>click</button>
</ComponentLoader>

如上例子,我们传了额外 props 属性,以及一个子元素给 chart 组件实例。

特别的,如果传递了 componentId,可以将该动态组件的 ID 固定下来,方便进行联动:

<ComponentLoader standalone componentName="chart" componentId="abc" />

但动态组件也有一些限制,如下:

  • 该方式渲染的组件元信息定义的 defaultPropsprops 不会生效,因为不存在于组件树中。
  • 该组件无法通过 deleteComponent 删除,也无法通过 setPropssetComponent 等修改,因为渲染完全由父组件控制,而不由组件树控制。
  • 不能用 setParent 改变这种组件的位置,因为其位置在代码中被固定了。

总结

其实 <Canvas /> 根节点本质上等价于 <ComponentLoader treePath="" />,即从根节点开始渲染一个组件实例。

所以提供 ComponentLoader 势必会让业务能力更灵活,在任意位置渲染组件,甚至渲染一个不存在于组件树的动态组件。

讨论地址是:精读《ComponentLoader 与动态组件》· Issue #482 · dt-fe/weekly

以上就是ComponentLoader 与动态组件实例详解的详细内容,更多关于ComponentLoader 动态组件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 2023年了该了解下WebComponent使用教程

    目录 正文 三项主要技术 1.Custom elements (自定义元素) 生命周期函数 2.HTML templates(HTML 模板) 3.Shadow DOM(影子 DOM) 动态创建 webComponent 组件例子 正文 WebComponent 是官方定义的自定义组件实现方式,它可以让开发者不依赖任何第三方框架(如Vue,React)来实现自定义页面组件:达到组件复用效果 一个简单例子,让页面显示 hello world: <body> <!-- 使用组件的方式 --&

  • Flutter Component动画的显和隐最佳实践

    目录 动画选择决策树 Implicit Animations——隐式动画 基本使用 使用场景 TweenAnimationBuilder Explicit Animations——显示动画 基本使用 AnimatedWidget AnimatedBuilder 动画选择决策树 Flutter中包含大量的动画组件和自定义动画方式,所以,在合适的场景下选择合适的动画实现方式就成了决定代码质量好坏的一个重要因素. Flutter中的动画从广义上来讲可以分为两类,一类是基于绘制的动画(Drawing-b

  • Web Components入门教程示例详解

    目录 Web Components不兼容IE 困境 Web Components核心技术 自定义元素 HTML模板(template.slot) shadow root(影子Dom) Web Components不兼容IE 2011年提出Web Components,为了解决代码复用问题,早于React.Vue: 相对于React.Vue组件,Web Components是原生组件,不限制接入方的技术,可以接入到React.Vue等技术框架中 困境 兼容性不足,需要主流浏览器的支持,需要平缓的过

  • Vue 自定义动态组件实例详解

    现在基于vue的UI组件库有很多,比如iview,element-ui等.但有时候这些组件库满足不了我们的开发需求,这时候我们就需要自己写一个插件. 举第一个栗子 用vue-cli搭建好项目目录之后,在src/components下面新建一个文件夹放我们要写的插件,如图所示: index.vue里写我们的组件,代码如下: index.js里面写index.vue的install方法,并用Vue.component注册组件,代码如下: 接下来我们要在默认的main.js里将刚刚写的index.js

  • vue组件编写之todolist组件实例详解

    我们在topNav这个页面上插入一个todolist子组件 我不知道怎么回事,这里的markdown的代码总是串行..所以代码看得不舒服,见谅啊,我最后会放github的源代码地址. 1. 父组件topNav中注册子组件,引入子组件 <template> <div> <p>下面这一行就是定义的组件名称</p> <todo-list></todo-list> <router-view></router-view>

  • 对Python中TKinter模块中的Label组件实例详解

    Python2.7.4 OS-W7x86 1. 简介 Label用于在指定的窗口中显示文本和图像.最终呈现出的Label是由背景和前景叠加构成的内容. Label组件定义函数:Label(master=None, cnf={}, **kw) 其中,kw参数是用来自定义lable组件的键值对. 2. 背景自定义 背景的话,有三部分构成:内容区+填充区+边框 <1>内容区参数有:width,length用于指定区域大小,如果显示前景内容是文本,则以单个字符大小为单位:如果显示的是图像,则以像素为单

  • vue的toast弹窗组件实例详解

    相信普通的vue组件大家都会写, 定义 -> 引入 -> 注册 -> 使用 ,行云流水,一气呵成,但是如果我们今天是要自定义一个弹窗组件呢? 首先,我们来分析一下弹窗组件的特性(需求): 0. 轻量 --一个组件小于 1Kib (实际打包完不到0.8k) 1.一般都是多处使用 --需要解决每个页面重复引用+注册 1.一般都是跟js交互的 --无需 在 <template> 里面写 <toast :show="true" text="弹窗消息

  • Flutter快速制作一个水印组件实例详解

    目录 正文 通过child属性将水印叠加给子组件 createWatermark方法 Watermark组件的完整代码 正文 项目开发的过程中,经常会遇到添加水印的需求,其作用无非就是防止重要信息通过截图外传.(虽然我觉得并没有什么卵用,但领导的需求是不容质疑的) 那么,作为一线码农的我,也只能屁颠屁颠的开搞. 通过child属性将水印叠加给子组件 水印组件,既然是组件,就是需要发扬Flutter套娃的精神,通过child属性将水印叠加给子组件. class Watermark extends

  • Linux静态库与动态库实例详解

    Linux静态库与动态库实例详解 1. Linux 下静态链接库编译与使用 首先编写如下代码: // main.c #include "test.h" int main(){ test(); return 0; } // test.h #include<iostream> using namespace std; void test(); // test.c #include "test.h" void test(){ cout<< &quo

  • vue实现简单表格组件实例详解

    本来想这一周做一个关于vuex的总结的,但是由于朋友反应说还不知道如何用vue去写一个组件,所以在此写写一篇文章来说明下如何去写vue页面或者组件.vue的核心思想就是组件,什么是组件呢?按照我的理解组件就是装配页面的零件,比如一辆车有大大小小许多零件组成,那么同样的一个页面,也是有许多组件构成的比如说头部组件 按钮组件等等,vue三大核心组件 路由 状态管理,路由控制页面的渲染,页面由组件组成,数据有vuex进行管理和改变.下面我会以一个简单的案例来说 第一步:构建一个简单的vue项目,老规矩

  • 基于vue+canvas的excel-like组件实例详解

    a vue component,基于vue的表格组件,主要解决大数据量的表格渲染性能问题,使用canvas绘制表格,同时支持类似excel的批量选中,复制黏贴删除,实时编辑等功能. vue-grid-canvas Install NPM / Yarn Install the package: npm install vue-canvas-grid --save Then import it in your project import Vue from 'vue' import Grid fro

  • Vue的事件响应式进度条组件实例详解

    写在前面 找了很多vue进度条组件,都不包含拖拽和点击事件,input range倒是原生包含input和change事件,但是直接基于input range做进度条的话,样式部分需要做大量调整和兼容性处理.即使做好了,将来需要修改外观,又是一番折腾. 基于以上两个原因,做了一个可以响应input和change事件(即一个是拖动进度条到某处,一个是在进度条某位置点击使其值变为该位置)的div实现的Vue组件,这样既满足了对进度条事件的需求,也带来了如有需求变动,样式修改很方便的好处. 效果图 以

  • Vuejs 单文件组件实例详解

    在之前的实例中,我们都是通过 Vue.component 或者 components 属性的方式来定义组件,这种方式在很多中小规模的项目中还好,但在复杂的项目中,下面这些缺点就非常明显了: 字符串模板:缺乏高亮,书写麻烦,特别是 HTML 多行的时候,虽然可以将模板写在 html 文件中,但是侵入性太强,不利于组件解耦分离. 不支持CSS:意味着当 HTML 和 JavaScript 组件化时,CSS明显被遗漏了 没有构建步骤:限制只能使用 HTML 和 ES5 JavaScript,而不能使用

随机推荐

其他