封面来源于网络。
一、前言
1. 背景
出于为了实现有关厂区的数字孪生项目,断断续续使用ThingJS平台开发一年左右,做一个使用感受的总结。
2. 业务场景
- 开发一个基于厂区的数字孪生项目,基于ThingJS低代码开发的页面分为div3d、div2d结构;
- div3d是3D场景展示的HTML节点,3D场景可以通过动画来模拟现实,并展示对应数据信息;
- div2d是2D图层展示的HTML节点,基于业务需要实现的数据和图表展示、功能操作等,其中功能操作可联动3D场景;
二、开发流程
1. 场景建模
使用「森园区」或「模模搭」,具有现成模型,建模需求不大,可以使用内置建模搭建场景;需要还原实际园区场景需要依靠 3D建模师 提供模型。
2. 低代码开发
具体可参考官方示例(需结合官方在线开发参考手册)
三、优缺点
优点
- 整合功能开发;
- 固定方法便捷引用;
- 0基础建模人员,可快速搭建简易建模;
缺点(偏开发方面)
a. 文件引入方式
THING.Utils.dynamicLoad(['/static/vendor/twitter-bootstrap/3.3.7/css/bootstrap.min.css','/static/vendor/twitter-bootstrap/3.3.7/js/bootstrap.min.js','/static/vendor/moment/moment.js'// ......
],function () {// 加载场景代码 var app = new THING.App({url: 'https://www.thingjs.com/static/models/factory', // 场景地址background: '#000000',env: 'Seaside',});// 加载场景后执行app.on('load', function (ev) {// 创建提示initThingJsTip(`制作项目过程中,平台支持上传页面资源, js 和 css 可以通过 dynamicLoad 进行引用`);});})
官网示例给出了上述 引入js和css 的方式,这种方式在具有引入大量文件需求的时候,会增加页面的初始加载时长;
问:这种引入文件的方式为什么会增加页面的初始加载时长?
答:
- 首先ThingJS低代码项目的运行流程大概是先依次加载文件,在加载3D场景,然后展示出整个项目场景;(THING.Utils.dynamicLoad()方法的参数1是文件地址数组。)
- 后期的项目业务量会越来越多、越来越复杂,需要加载的JS、CSS文件更多;(笔者所开发的项目按照功能模块来写,至少40个JS文件,每次加载时长在30s~1min多之间。)
- 开发过程中会有引入第三方插件的需求,随之我们需要加载的文件会越来越多;(dayjs.js、js.cookie.js、bootstrap.min.js......)
b. 2D页面结构添加方式
/*** 利用模板字符串 创建页面元素并添加到div2d中*/
function createButton() {// 使用 bootstrap 样式var template =`<button class="btn btn-default" type="button" style="position:absolute;left:20px;top:20px;z-index:2">当前时间</button>`;var btn = $('#div2d').append($(template));return btn;
}
上述是ThingJS低代码平台开发2d平面图层添加HTML元素节点的方式(即:模版字符串【``】)
也就是说,你所有的HTML节点都要使用模版字符串进行添加;
举例:导航栏、侧窗、弹窗、按钮等......基本所有图层都需要使用模版字符串进行拼接、添加;
(可以参考低代码平台示例中是如何添加2d图层的。)
(这个博客也有提到这种方式)
c. 无法使用CSS预处理器
因为文件引入方式不支持CSS预处理器相关后缀文件引入,所以笔者一般的开发方式是:在VSCode中新建html文件,写好页面结构,依靠Less/Sass进行写样式,然后分别将html结构通过模版字符串添加到div#div2d的节点中、将解析出的CSS文件导入低代码项目中。
d. 无法很好地使用模块化开发
ThingJS不支持目前主流的JS模块化方案;
该博客中有提到 引入js和css 的方式可以作为一个模块化文件引入方案,但是博客中有提到: “如果要实现一个较为庞大复杂的业务场景时,就不太方便了” ,也正是笔者担心的。
因为前期开发获取到ThingJS开发方式的参考极少甚至没有(只能参考ThingJS低代码示例),所以笔者一直在使用的是 引入js和css 的方式,算是全局变量了......(因此也引发了后续编译或混淆后的报错问题......)
主流的JS模块化方案无法使用,可以尝试以下方案:(两种方式笔者都未曾验证是否存在其他问题)
1. 命名空间
使用对象来创建命名空间,将相关功能和变量组织在命名空间下,以避免全局变量的冲突。
使用命名空间的方式,你可以在全局范围内只定义一个对象,然后将模块的功能和变量添加为该对象的属性。
var MyNamespace = {// 模块1module1: { // ... },// 模块2module2: { // ... },// ...
};
2. 模块模式(推荐)
使用函数返回对象的方式创建模块,将模块内部的变量和函数隐藏起来,只暴露需要暴露的接口。
var MyModule = (function() {var privateVariable = '私有变量';function privateFunction() { // 私有函数 }function publicFunction() { // 公有函数 }return { publicFunction: publicFunction };
})();
MyModule.publicFunction(); // 调用公有函数
e. 开发无报错,上线报错
原因:
上线前平台内部的编译工具或混淆器错误地重复定义了同一个变量名。
待解决理由:
项目会因为混淆器定义的变量莫名地报错,每次运行项目无法保证具体哪个功能无法使用。
优化方案:
尝试更新或更改编译工具或混淆器的配置(第三方平台,无法更新或更改配置)- 全局变量包装在一个自定义的命名空间对象中(未做尝试,无法保证不继续有混淆器重复定义变量的问题)。
缺点:
项目复杂后,无法保证声明的命名空间对象不会被混淆器重复定义同一个变量名。
f. 初始化加载
原因:
- (模型方面)当场景内物体过多时也有可能会导致场景加载缓慢,卡顿。
- (源码方面)平台没有提供构建工具来处理源代码,所以无法很好的进行文件压缩、代码合并、文件优化等操作。
待解决理由:
项目初始化加载时间过长
优化方案:
创建一个新的项目,将源码使用压缩网站进行压缩,将其复制到新的项目中。
(在老项目中实现功能,然后压缩代码复制到新项目,引用新项目链接)
缺点:
- 该优化方案只是优化的方法之一,不能保证优化效果显著,后期项目代码量提升,依旧会影响加载时间;
- 开发方式受限,增加开发工作量,并且不能保证压缩后代码不出现问题;
影响加载速度的原因:
- 基于平台引入文件的方式,初始化时依次全部加载出来
- 资源文件大小和数量
- 第三方插件和库
- 网络速度和延迟
- 服务器性能和响应时间
......
四、总结
在编码方面,笔者的编码方式和博客中的描述基本一致:“由于平台提供的代码编码端体验不佳,我们不得不先在本地进行开发,再将相关代码复制到在线平台,而调试修改代码也是如此繁琐”。
个人感觉至少现阶段的ThingJS还是比较适合去做一些简单的业务场景、数据交互简单的项目,类似于大屏展示,这种纯数据展示;如果要实现一个较为庞大复杂的业务场景时,就不太方便,开发难度也会随之增加。
不得不承认ThingJS有一定的优点,但是相对开发来说,这些优点是可以被缺点抵消掉的;
如果一个项目开发不方便,不仅会影响到开发周期,还会提高后期项目的维护成本......