低代码平台组件间通信方案复盘

news2024/11/24 7:27:50

背景介绍

3年前我开发了一款零代码搭建平台 H5-Dooring, 主要目的是想用更低的成本, 更快的效率, 上线 web 页面(其实是不想写重复的代码了,写麻了). 好在陆陆续续折腾了3年, 目前已经可以满足基本的页面设计和搭建能力, 并能快速上线页面.

之前也在社区分享了很多低代码零代码的技术实现, 接下来继续和大家聊聊低代码平台中组件与组件之间的通信方案设计.

可视化搭建平台的基本能力

根据我自己设计可视化搭建平台的经验, 其需要具备最最基本的两个能力:

  • 静态页面设计能力(也就是可以用可视化平台制作我们想要的页面的能力)

  • 组件交互能力(制作好静态页面之后, 页面元素能具备一定的交互, 比如跳转链接, 打开弹窗等)

以上的能力可以让我们将页面通过拖拽的方式搭建出来:

d8da7f8741c442df3acf749928325105.png

虽然这已经可以满足很多展示型的需求, 但是仍然存在局限性, 比如可视化平台的组件与组件之间, 没办法相互通信.

更灵活自主的可视化搭建平台

这里给大家举一个实际的场景, 比如我们要做一个转盘H5页面, 它由转盘组件和按钮组件组成, 当点击按钮时, 转盘开始运动:

980e913086a5ff4d9ff8a31bde6ff51d.png

这种场景就需要转盘组件和按钮组件相互通信, 来实现交互功能. 所以在可视化搭建平台中, 如果能实现组件间的通信, 那将覆盖更多的业务场景, 从而为个人或者企业带来更大的价值.

0e1613a6736cddb124c1832504ef7ca9.png

接下来我将和大家分享一下低代码平台中组件间通信的几种方案, 共大家学习参考.

组件间通信的几种实现方案

c607450ff6f7fe277a5589328f1ddf60.png

说到组件通信我们也许并不陌生, 比如在 vue 或者 React 框架中, 经常会涉及到父子组件通信以及组件与组件间的通信, 常用的方案也有很多, 比如:

  1. props/$emit

  2. 子组件向父组件传值

  3. eventBus($emit/$on)

  4. vuex / redux

  5. $attrs/$listeners

  6. provide/inject

当然还有很多方式能帮我们实现传统组件间的通信, 那我们在低代码组件中, 也可以参考类似的方式来实现, 但是唯一的区别是需要设计一套规则, 来保证组件间通信可以通过用户配置的方式来运转.

接下来我们来分析几种低代码组件间的通信方案.

1.websocket

在设计组件通信方案前, 我们需全局维护一个公共的状态, 拿 H5-Dooring可视化平台 举例, 我们用 redux 管理公共状态, 组件间通信本质就是触发公共状态的更新:

9b6674ed6e429f1d6c916a5295fe85a5.png

为了保证低代码组件库足够纯净, 比如不应该在组件里连接 redux, 所以我们需要把 redux 触发器 dispatch 放在页面的全局, 这里就可以用 websocket, 在组件里触发 socket 指令,  在页面全局来监听, 并触发 dispatch :

a54738cc07b042aa7c5ce0a08058236c.png

当然使用 socket 的方式仍然会让低代码组件库负重前行(虽然能实现更自由的通信场景, 比如组件自更新, 生命周期回调, 控制业务钩子等), 因为我们不得不为其搭建 socket 服务, 并且需要为其设计稳定的通信桥梁, 比如 socket 心跳连接等.

2.iframe通信 postmessage

利用 iframepostmessageAPI 虽然也能实现组件间通信, 但是我们需要设计一套通信机制, 保证 iframe 能接受组件传送的指令, 并对外暴露共享状态:

5e434c3c9a0d1f2886324bfdc5920fb2.png

我们从 Iframe 的通信模式可以发现它不仅可以作为中间桥梁起到通信作用, 有点类似于 eventBus的模式, 而且还可以实现页面间的通信, 比如目前很多微前端架构的底层支持也有采用 iframe 来设计的. 但是对于更细粒度的低代码组件来说, 有点小题大作了.

接下来给大家分享一下 iframe 通信的基本代码实现:

// 父页面和子页面通信
// A.html (父)
<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>
const msg = {
    name: "H5-Dooring"
  }
window.onload = () => {
  // 自动调用必须放在onload中,通过事件调用则不用
  // let frame = document.querySelector("#Bframe").contentWindow
  let frame = window.frames[0]
  frame.postMessage(msg, "http://h5.dooring.cn/preview")
}

// B.html
window.addEventListener("message", (e) => {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})

// 子页面和父页面通信
// A.html (父)
<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>
window.addEventListener("message", (e) => {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})

// B.html
const msg = {
  name: "Dooring H5"
}
window.top.postMessage(msg, "http://h5.dooring.cn/preview")

3.Event Emitters

Event Emitters 的方式我觉得是最适合低代码组件间通信的方案, 类似于 js 里的事件监听机制, 我们可以给 dom 绑定监听, 并暴露事件给用户来实现手动触发机制. (虽然不一定是用户手动触发, 也有一种情况是逻辑触发, 比如当页面某个组件到达某一状态的时候, 后自动触发事件, 来改变其他组件的状态)

Event Emitters 类似一种观察者模式, 我们可以利用 javascript 的设计模式来实现它, 并在组件内部来监听或者触发, 一个简单的实现如下:

interface Events {
  [key: string]: Function[];
}

export class EventEmitter {
  public events: Events;
  constructor(events?: Events) {
    this.events = events || {};
  }

  public subscribe(name: string, cb: Function) {
    (this.events[name] || (this.events[name] = [])).push(cb);

    return {
      unsubscribe: () =>
        this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1)
    };
  }

  public emit(name: string, ...args: any[]): void {
    (this.events[name] || []).forEach(fn => fn(...args));
  }
}

具体设计流程有点像我之前设计的 iframe 通信架构, 不过使用起来会更简单:

ac6a7a44f2fcfb407c54fd8e822f605a.png

低代码组件事件队列设计

以上只实现了组件的通信, 并没有将通信和实际的应用场景结合起来, 比如低代码用户需要如何操作,才能实现组件通信. 这里我之前也设计了一套模型:

add28f4d5caddd583d3def75116d4990.png

每个组件都有一套事件列表, 用户可以给一个组件添加多个交互事件, 在第代码内部通过循环遍历来依次触发事件队列:

4b832b6fdf8b2becf5dafe8022204b04.png

事件通信就可以用上面介绍的 Event Emitters来实现, 具体的低代码模式可以参考我之前的项目:

H5-Dooring可视化低代码平台

总结

后续我会继续和大家分享一下 H5-Dooring 低代码的更多实践和思考, 如果大家对可视化低代码感兴趣也可以参考我的低代码可视化专栏.

下一篇文章我会和大家分享一下低代码印章组件的实现方案, 大家有更多好的建议也可以随时和我反馈.

H5-dooring低代码

0c66a92a02c4443b2b4bec01093b4e72.png
H5-dooring低代码

V6.Dooring可视化大屏搭建平台

8589e3656ae4a302fc6b74f648bd0591.png
V6.Dooring可视化大屏搭建平台

2016056e226fbc3a5e7ca9301f8a07a9.gif

从零搭建全栈可视化大屏制作平台V6.Dooring

从零设计可视化大屏搭建引擎

Dooring可视化搭建平台数据源设计剖析

可视化搭建的一些思考和实践

基于Koa + React + TS从零开发全栈文档编辑器(进阶实战

点个在看你最好看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/142010.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高、低成本MEMS惯导系统姿态、位置、速度更新算法的对比

高、低成本MEMS惯导系统姿态、位置、速度更新算法的对比一、高成本MEMS惯导系统姿态、位置、速度更新算法1、速度更新2、位置更新3、姿态更新4、程序仿真及实验结果4.1 主函数4.2 子函数4.3 实验结果一、低成本MEMS惯导系统姿态、位置、速度更新算法1、速度更新2、位置更新3、姿…

乾元浩在创业板IPO终止:主要生产禽用疫苗产品,中农大是股东

2023年1月4日&#xff0c;深圳证券交易所披露的信息显示&#xff0c;乾元浩生物股份有限公司&#xff08;下称“乾元浩”&#xff09;提交了撤回上市申请文件的申请&#xff0c;保荐人中信证券也撤回对该公司的保荐。因此&#xff0c;深交所终止了乾元浩首次公开发行股票并在创…

程序员述职报告

程序员述职报告笔者能力有限&#xff0c;仅供参考。做研发的小伙伴&#xff0c;不太擅长于写PPT&#xff0c;对于更高一级别的领导&#xff0c;可能只有年终述职的时候才能全面的了解你的工作。所以需要我们在PPT中表达自我价值&#xff0c;突出角色职责。让领导更清楚的认识你…

访问数据库超时问题排障

1 排障过程 系统从圣诞节那天晚上开始&#xff0c;每天晚上固定十点多到十一点多这个时段&#xff0c;大概瘫痪1h左右&#xff0c;过这时段系统自动恢复。系统瘫痪时的现象就是&#xff0c;网页和App都打不开&#xff0c;请求超时。系统架构&#xff1a; 整个系统托管在公有云…

图解数据结构:盘点链表与栈和队列的那些血缘(单双链表模拟实现栈和队列)

写在前面 Hello&#xff0c;各位盆友们&#xff0c;我是黄小黄。关于前一段时间为什么拖更这件事&#xff0c;这里给大家说一句抱歉。笔者前段时间忙于ddl和一些比赛相关的事件&#xff0c;当然还有些隐藏任务&#xff0c;所以博文更新就放缓了。  这里还需要做一下对以后博文…

计算机原理一_计算机的组成、进程与线程

目录儿一、计算机组成二、进程与线程2.1 线程的切换2.2 CPU的并发控制2.2.1 关中断2.2.2 缓存一致性协议2.2.2.1 缓存Cache2.2.2.2 缓存行Cache Line2.2.2.3 缓存一致性拓展&#xff1a;超线程2.2.3 内存屏障2.2.3.1 CPU的乱序执行拓展1&#xff1a;java 的 this 溢出问题拓展2…

Linux(一):Linux基本结构

一、Linux系统划分 linux系统分为用户区、内核区 1.1分区目标 保护数据和硬件安全&#xff0c;对系统进行分区也就是进程分区&#xff0c;当处于用户态&#xff0c;只能访问用户区&#xff0c;用户无法修改内核&#xff0c;保证硬件安全&#xff0c;操作系统不易损坏&#…

【Qt】QMainWindow应用程序窗口类简单介绍

QMainWindow介绍 QMainWindow是一个为用户提供主窗口程序的类&#xff0c;是许多应用程序的基础&#xff0c;包含的组件有&#xff1a; 菜单栏QMenuBar&#xff0c;一个主窗口最多只能有一个菜单栏&#xff1b;包含一个下拉菜单项的列表&#xff0c;这些菜单项由QAction动作类…

【git版本控制】| git版本控制操作命令(全)

文章目录一、简介二、工作模式1 集中式&#xff08;CVS、SVN&#xff09;2 分布式Git三、Git1 工作模式2 git工作流程3 工作区和版本库4 注意事项5 基本操作5.1 创建本地版本库5.2 初始化本地版本库5.3 .git目录的作用5.4 创建用户5.5 其他操作6 git分支7 常见警告8 免密登录9 …

interface接口--GO面向对象编程思想

一、interface接口 interface 是GO语言的基础特性之一。可以理解为一种类型的规范或者约定。它跟java&#xff0c;C# 不太一样&#xff0c;不需要显示说明实现了某个接口&#xff0c;它没有继承或子类或“implements”关键字&#xff0c;只是通过约定的形式&#xff0c;隐式的…

【C语言进阶】自定义类型:结构体,枚举,联合体

目录 1、结构体的声明 1.1 结构体基础知识 1.2 结构体的声明 1.3 特殊的声明 1.4 结构体的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 ​编辑1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2 位段的内存分配 2.3 位段的跨平台问…

【owt-server】代码结构及新增一个agent

owt server 官方 5.0 仓库:代码结构 manage console manage api portal sip portal 与agent 并列 agent又有很多种类。 启动脚本 启动一个新的agent 比如streaming-agent streaming-agent )cd ${OWT_HOME}/s

分布式id

分布式id一 什么是分布式系统唯一ID二 分布式系统唯一ID的特点三 分布式系统唯一ID的实现方案3.1 基于UUID3.2 基于数据库自增id3.3 基于数据库集群模式3.4 基于Redis模式3.5 基于雪花算法&#xff08;Snowflake&#xff09;模式3.6 百度&#xff08;uid-generator&#xff09;…

Python爬虫数据到sqlite实例

参考链接:https://blog.csdn.net/qq_45775027/article/details/115319253最近需要使用到爬虫数据库&#xff0c;原文中作者有些没补齐&#xff0c;略作修改之后跑通了。主要修改&#xff1a;1.调整了数据获取的正则表达式&#xff1b;2. 改了一下数据库的table名和定义名字&…

基于Java+SpringBoot+vue+element实现前后端分离牙科诊所管理系统详细设计

基于JavaSpringBootvueelement实现前后端分离牙科诊所管理系统详细设计 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目…

【Linux】虚拟地址空间 --- 虚拟地址、空间布局、内存描述符、写时拷贝、页表…

该吃吃&#xff0c;该喝喝&#xff0c;遇事儿别往心上隔&#x1f60e; 文章目录一、虚拟地址空间1.虚拟地址的引出&#xff08;看不到物理地址&#xff0c;只能看看虚拟地址喽&#xff09;2.虚拟地址空间布局&#xff08;五个段&#xff09;3.感性理解一下虚拟地址空间&#xf…

【C++修炼之路】C++入门(上)

&#x1f451;作者主页&#xff1a;进击的安度因 &#x1f3e0;学习社区&#xff1a;进击的安度因&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C修炼之路 文章目录一、前言二、第一个 C 程序三、C 关键字(C98)四、命名空间1、命名空间的定义2、命名空间…

C++ Prime课后习题第一章编程

编程一个C程序&#xff0c;它显示您的姓名和地址。#include <iostream>int stonetolb(int); int main() {using namespace std;cout << "zzz ";cout << "闵行"<<endl;return 0; }编写一个程序&#xff0c;要求用户输入一个以long…

3台机器配置hadoop集群_Hadoop+Hbase 分布式集群架构

安装搭建Hadoop1、 配置说明本次集群搭建共三台机器&#xff0c;具体说明下&#xff1a;主机名IP说明nn01192.168.1.51DataNode、NodeManager、ResourceManager、NameNodedn01192.168.1.52DataNode、NodeManager、SecondaryNameNodedn02192.168.1.53DataNode、NodeManager2 、安…

基于浏览器的 PDF 编辑器:RAD PDF for ASP.NET

版本 3.34 改进的 PDF 收藏/投资组合支持和服务器 API 改进 Ω578867473功能更新 为更基本的 PDF 文件损坏/语法错误添加了更正添加了 PdfButtonField.NamedAction 属性添加了 PdfButtonField.IsNamedAction 属性添加 PdfButtonField() 构造函数 - PdfButtonFields 可以由服…