IoT Studio可视化搭建平台编辑历史功能的思考与探索

简介: 在前端可视化搭建领域中“重做”和“撤销”这两个功能已经是标配中的标配,毕竟只要有用户行为的地方就可能会有出错,这两个功能无疑就是为用户提供了“后悔药”。目前有各种各样的可视化搭建平台,本文介绍IoT Studio可视化搭建平台在编辑历史功能上的设计与思考。

image.png

作者 | 远坂
来源 | 阿里技术公众号

一 背景

在前端可视化搭建领域中“重做”和“撤销”这两个功能已经是标配中的标配,毕竟只要有用户行为的地方就可能会有出错,这两个功能无疑就是为用户提供了“后悔药”。目前有各种各样的可视化搭建平台,本文介绍IoT Studio可视化搭建平台在编辑历史功能上的设计与思考。

image.png

二 实现思路

1 页面DSL的维护

在IoT Studio可视化搭建平台中,我们通过页面的抽象语法树来维护页面状态,页面信息和组件信息都记录在对应节点上:

image.png

PageNode: {componentName: 'page1',id: 'page1',props: {},children: [ComponentNode: {componentName: 'component1',id: 'component1',props: {width: 800,height: 1000,color: '#ffffff'},children: []},ComponentNode: {componentName: 'component2',id: 'component2',props: {},children: []},ComponentNode: {componentName: 'component3',id: 'component3',props: {},children: []},]
}

在页面保存时,页面配置会作为JSON文件上传至OSS。

2 重做与撤销

快照法

在每次编辑页面时,将页面的信息进行深拷贝存入历史记录中。在进行重做和撤销时从历史记录中取出对应的快照,用快照代替当前页面状态,即可完成一次历史记录的操作。

在这种方法下,通常使用一个指针来指向当前的页面状态。如下图:

image.png

进行后退操作后,指针指向之前的某次快照,页面恢复到P3时的状态:

image.png

再次进行编辑时,指针指向新的状态P5 :

image.png

快照法的特点:

  1. 实现比较简单,页面信息全量进行深拷贝即可。
  2. 历史记录之间的切换灵活。
  3. 当页面信息很大时,十分占用存储空间。

指令法

IoT Studio使用的是这种方法。

我们为每一次操作定义两个方法:execute与undo,以及将“操作”抽象为Operation。

在execute中执行这次操作的正向操作,在undo中实现逆向操作。

export abstract class Operation<T = void> {  /*** 逆向操作*/protected abstract undo(): T;/*** 正向操作*/protected abstract execute(): T;
}

每进行一次编辑操作,其实就是创建一次Operation并执行其execute方法,随后如果需要撤销就执行其undo方法。

image.png

指令法的特点:

  1. 相对快照法,在页面配置复杂时,能节省不少存储空间。
  2. 不同的Operation其execute和undo逻辑很可能会不一样,有一定的逻辑开发成本。
  3. 跨多个历史记录的重做或撤销,需要执行他们之前所有的execute或undo。例如,上图中如果从O3到O1需要执行2次undo。这一点没有快照法便利。

3 实现细节

在上文里提到了IoT Studio使用的是指令法。

Transation

在实际业务开发中,很多场景会涉及到一次性编辑多个组件,即涉及多个Operation实例。于是在Operation基础上有了Transaction——事务的概念,Transaction下维护了一份Operation实例List,每当有execute或者undo执行时,会遍历Operation List中的Operation实例执行其execute或undo方法。

image.png

双向链表

IoT Studio中的操作历史是基于双向链表实现的,每个链表节点维护一个Transaction实例。链表节点末端的execute结果既是最新的操作历史。

链表之前通过forwardCurrent和backforwardCurrent方法进行节点状态的切换。

image.png

Class Manager {backwardCurrent(): boolean {if (this._current?.prev) {this._current.value.operation.undo();this._current = this._current.prev;this._validLength -= 1;return true;}return false;}forwardCurrent(): boolean {if (this._current?.next) {this._current.next.value.operation.execute();this._current = this._current.next;this._validLength += 1;return true;}return false;}addAfterCurrent(item: OperationResult<any>) {if (nextNode) {nextNode.prev = undefined;this._length = this._validLength;}this._current.next = { value, prev: this._current };this._current = this._current.next;}
}

每当有新的编辑操作时,会通过addAfterCurrent插入新的节点。

image.png

4 总结

Operation是实现重做和撤销的最小指令实例,通过Operation不同子类实现不同的execute和undo方法,从而实现重做和撤销的具体逻辑。

Transaction中维护了Operation实例数组,我们在进行业务逻辑开发中对组件进行属性设置时是以Transaction实例为单位进行业务逻辑开发。

维护了一个双向链表来对Transaction实例进行管理,从而实现可视化搭建的操作历史功能。

image.png

三 探索

在实现思路中我们提到了“快照法”和“指令法”,对比两者的优缺点,不难发现主要矛盾是在体积与维护成本上。那么有没有一种办法能兼顾二者的优点呢?下面两个工具可以提供一些思路:

immutable.js + 快照法

在JS中对象是引用赋值,在保存对象时往往会使用深拷贝规避这个问题,但是这样会造成CPU和内存的浪费,这也是快照法的缺点所在。

image.png

immutable使用持久化数据结构,在使用旧数据创建新数据的时候,会保证旧数据同时可用且不变,同时为了避免深度复制复制所有节点的带来的性能损耗,immutable使用了结构共享,即如果对象树种的一个节点发生变化,只修改这个节点和受他影响的父节点,其他节点则共享。

在实现操作历史功能时,使用immutable存储数据,能解决数据复用的问题。immutable.js + 快照法可以组合使用。据我所知公司的@ali/visualengine使用的就是这个方案。

Git

每次我们运行 git add 和 git commit 命令时,Git 所做的工作实质就是将被改写的文件保存为数据对象, 更新暂存区,记录树对象。

image.png

我们在使用git维护项目时,理论上随着git commit的次数越来越多,文件对象会越拉越大,但实际上体积并没有变的很大。事实上git在权衡时间和空间后帮我们做了部分优化,较早的版本会保存diff,较新的本会保存全量数据对象。

Git 是如何做到这点的?Git 打包对象时,会查找命名及大小相近的文件,并只保存文件不同版本之间的差异内容。 你可以查看包文件,观察它是如何节省空间的。
同样有趣的地方在于,第二个版本完整保存了文件内容,而原始的版本反而是以差异方式保存的——这是因为大部分情况下需要快速访问文件的最新版本。最妙之处是你可以随时重新打包。Git 时常会自动对仓库进行重新打包以节省空间。当然你也可以随时手动执行 git gc 命令来这么做。

原文链接

本文为阿里云原创内容,未经允许不得转载。 

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

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

相关文章

云计算架构设计6大原则,你遵循了吗?| 赠书

作者 | 吕昭波 2006年&#xff0c;第一个云计算&#xff08;Cloud Computing&#xff09;产品诞生&#xff0c;云计算的概念也被提出&#xff0c;现在云计算几乎已经渗入所有的行业和应用场景中。我们不一定能直接感受到云计算对日常生活、工作、学习的影响&#xff0c;但作为I…

python写自动化工具_微软最强 Python 自动化工具开源了!不用写一行代码!

1. 前言最近&#xff0c;微软开源了一款非常强大的 Python 自动化依赖库&#xff1a;playwright-python它支持主流的浏览器&#xff0c;包含&#xff1a;Chrome、Firefox、Safari、Microsoft Edge 等&#xff0c;同时支持以无头模式、有头模式运行playwright-python 提供了同步…

复杂推理模型从服务器移植到Web浏览器的理论和实战

简介&#xff1a; 随着机器学习的应用面越来越广&#xff0c;能在浏览器中跑模型推理的Javascript框架引擎也越来越多了。在项目中&#xff0c;前端同学可能会找到一些跑在服务端的python算法模型&#xff0c;很想将其直接集成到自己的代码中&#xff0c;以Javascript语言在浏览…

国家网络安全宣传周:勒索病毒利如刀,上网备好技能包

简介&#xff1a; 近年来&#xff0c;勒索病毒携带着日趋成熟的手段革新和愈发隐蔽、复杂的“进化”能力&#xff0c;开启了“重装上阵”的疯狂模式&#xff0c;“出镜率”大有提高。由于大型政企机构的网络资产价值高&#xff0c;就成了勒索病毒的头号“猎物”。 政企机构信息…

漫画:什么是“低代码”开发平台?

作者 | 小灰来源 | 程序员小灰什么是低代码&#xff1f;其实&#xff0c;这并不是最近才出现的新概念。自从计算机诞生以来&#xff0c;人们就一直在想方设法提升计算机程序编写的效率。从最初的机器语言&#xff0c;发展到现在的C、Java、Python等高级语言&#xff1b;从完全独…

OpenKruise 如何实现应用的可用性防护?

简介&#xff1a; OpenKruise 在 2021.9.6 发布了最新的 v0.10.0 版本新增了弹性拓扑管理和应用安全防护等能力&#xff0c;本文将为大家揭晓 OpenKruise 是如何实现应用的可用性防护能力。 前言 OpenKruise 是阿里云开源的云原生应用自动化管理套件&#xff0c;也是当前托管…

Serverless 工程实践 | Serverless 应用优化与调试秘诀

简介&#xff1a; 本文将以阿里云函数计算为例&#xff0c;提供了在线调试、本地调试等多种应用优化与调试方案。 作者&#xff5c;刘宇 前言&#xff1a;本文将以阿里云函数计算为例&#xff0c;提供了在线调试、本地调试等多种应用优化与调试方案。 Serverless 应用调试秘…

新一代容器平台ACK Anywhere,来了

简介&#xff1a; 近日&#xff0c;阿里云容器服务全面升级为ACK Anywhere&#xff0c;让企业在任何需要云的地方&#xff0c;都能获得一致的容器基础设施能力。 5G、AR、AIoT 等场景在推动新一代云架构的演进&#xff0c;而容器重塑了云的使用方式。 近日&#xff0c;阿里云…

高密自智,体小量大,希捷Exos Corvault存储系统为数据洞察赋能

2022年2月24日——全球领先的海量数据存储基础设施解决方案提供商希捷科技&#xff08;NASDAQ&#xff1a;STX&#xff09;在线上举办了主题为“高密自智&#xff0c;体小量大”的新一代PB级自修复存储系统——Exos Corvault新品鉴赏会。 此次鉴赏会邀请到了E企研究院首席研究…

Apache Flink 在汽车之家的应用与实践

简介&#xff1a; 汽车之家如何基于 Flink 上线了 AutoStream 平台并持续打磨。 本文整理自汽车之家实时计算平台负责人邸星星在 Flink Forward Asia 2020 分享的议题《Apache Flink 在汽车之家的应用及实践》。主要内容包括&#xff1a; 背景及现状AutoStream 平台基于 Flink …

以色列安全厂商Check Point发布全新logo与重要安全新品,持续深耕中国市场

作者 | 宋慧 出品 | CSDN 云计算 2022年伊始&#xff0c;以色列老牌安全厂商Check Point在自家主办的安全行业大会CPX360上&#xff0c;正式宣布将启用全新企业logo以及企业口号。 Check Point公司中国区总经理陈石磊在对国内媒体分享时指出&#xff1a;“公司1993年成立时&am…

Facebook宕机背后,我们该如何及时发现DNS问题

简介&#xff1a; 国庆期间&#xff0c;Facebook 及其旗下 Instagram 和 WhatsApp 等应用全网宕机&#xff0c;停机时间将近 7 小时 5 分钟&#xff0c;Facebook 市值损失 643 亿美元。针对Facebook的宕机问题&#xff0c;我们该如何未雨绸缪&#xff0c;看看云拨测如何帮助客户…

KubeVela 1.1 发布,开启混合环境应用交付新里程碑

简介&#xff1a; KubeVela 作为一个开箱即用、面向现代微服务架构的应用交付与管理平台&#xff0c;今天正式发布了 1.1 版本&#xff0c;以更加用户友好和完善的功能集&#xff0c;开启了“让混合环境应用交付更加简单高效”的重要里程碑。 在云原生理念迅速普及的今天&…

云原生消息、事件、流超融合平台——RocketMQ 5.0 初探

简介&#xff1a; 今天分享的主题是云原生消息事件流超融合平台 RocketMQ 5.0 初探&#xff0c;内容主要分为三个部分&#xff1a; 首先&#xff0c;带大家回顾业务消息领域首选 RocketMQ 4 发展历史以及 4.x 版本的演进与发展。 其次&#xff0c;会为大家详细介绍 RocketMQ 5.…

mysql查找无根节点sql_SQL 双亲节点查找所有子节点的实现方法

怎么保存树状结构的数据呢&#xff1f;在 SQL 中常用的是双亲节点法。创建表如下CREATE TABLE category ( id LONG, parentId LONG, name String(20) )INSERT INTO category VALUES ( 1, NULL, Root )INSERT INTO category VALUES ( 2, 1, Branch1 )INSERT INTO category VALUE…

一文看懂微服务背后的技术演进与应用实践

简介&#xff1a; 2021年7月2日&#xff0c;阿里云用户组&#xff08;AUG&#xff09;第一次线下活动在济南召开。阿里云云原生资深专家李国强结合自身微服务领域经验&#xff0c;现场跟数十家山东企业分享了云原生的代表技术之一“微服务”的演进和应用实践。本文根据作者的现…

1 分钟记住 docker 镜像和容器常用基本命令

作者 | xiaochuhe来源 | CSDN博客镜像常用基本命令查看自己服务器中docker 镜像列表docker images搜索镜像docker search 镜像名 docker search --filterSTARS9000 mysql 搜索 STARS >9000的 mysql 镜像拉取镜像docker pull 镜像名 docker pull 镜像名:tag运行镜像docker ru…

业界首个机密计算容器运行时—Inclavare Containers正式进入CNCF!

简介&#xff1a; Inclavare Containers 通过云原生计算基金会&#xff08;CNCF&#xff09;TOC 投票正式成为 CNCF 官方沙箱项目。 作者&#xff5c;彦荣 2021 年 9月 15 日&#xff0c;Inclavare Containers 通过云原生计算基金会&#xff08;CNCF&#xff09;TOC 投票正式成…

python 矩阵库_NumPy 矩阵库(Matrix)

NumPy 中包含了一个矩阵库 numpy.matlib&#xff0c;该模块中的函数返回的是一个矩阵&#xff0c;而不是 ndarray 对象。由 m n 个数aij排成的 m 行 n 列的数表称为 m 行 n 列的矩阵&#xff0c;简称 m n 矩阵。记作这 mn 个数称为矩阵 A的元素&#xff0c;简称为元&#xff…

顺丰科技 Hudi on Flink 实时数仓实践

简介&#xff1a; 介绍了顺丰科技数仓的架构&#xff0c;趟过的一些问题、使用 Hudi 来优化整个 job 状态的实践细节&#xff0c;以及未来的一些规划。 本文作者为刘杰&#xff0c;介绍了顺丰科技数仓的架构&#xff0c;趟过的一些问题、使用 Hudi 来优化整个 job 状态的实践细…