
您可能已经知道,Angular已经存在于许多平台上:
好吧,当然,这里没有足够的台式机(现在还不谈论Electron)。
为了创建桌面应用程序,有许多使用模板的解决方案,例如JavaFx,Qt,WPF之类的解决方案。 除了最后一个,所有这些都是跨平台的。
但是,如果我们想使用熟悉的框架并在其上创建本机应用程序,该怎么办? 实际上,这就是我所做的。
首先,我研究了当前可用的功能,以及在Angular下可能已经完成的操作。
实际上,我想以此方式证明您可以在Angular上做任何事情,而且我已经连续几年做了各种各样的事情 。
搜寻
libui节点
它是一个轻巧的可移植GUI库,可针对其支持的每个平台利用GUI的本机功能。 它是电子的替代品。
一个简单的应用示例:
const win = new libui.UiWindow('Test window', 800, 600, false);
在引擎盖下,他有简单的libui资料夹。 (libui:用于C的可移植GUI库)。 所有这些都是通过node-gyp进行的,该工具旨在为Node.js编译本机扩展。 libui-node包含30多个现成的组件,如果您突然决定创建一些自定义组件,则需要深入研究C语言中的代码。此外,这些组件本身是2年前编写的,从那时起更新。 也许一切都很好,所以不需要进行更改,这30个组件足以进行开发,或者根本没有人需要该项目。
好吧,实际上,完成的应用程序可能如下所示:
libui节点
质子和维多
这里有点有趣,质子本机和vuido是同一个libui节点,仅在React和Vue下。 相应的包装器被编写在libui-node的组件下。 尽管github上有很多星星(9k和6k),但这些项目还是被放弃了,几乎没有人使用它们。 在我能找到的所有东西中,这些都是非常简单的应用程序。 我发现的另一个问题是UI本身的自定义问题,不可能在libui中完成,该项目的作者正在考虑重写Qt中的所有内容。
Libui本身非常适合编写各种绑定,发烧友甚至在php中也将其拖动
完成的应用程序可能如下所示:
质子化的
没有自定义的界面非常无聊,因此该选项立即消失了。
还是接受Qt?
Qt,JS,CSS
当然,您听说过Qt,而且它随处可见,但很少有人听说过它现已与Javascript集成在一起。 QML允许使用属性绑定器以声明方式构造用户界面,从而扩展现有QML元素的功能。 当然,这比Web上的Javascript更严格。 您可以使用QML对象编写类似于ES5的内容,但是您将没有DOM API。
简要说明一下,如何在C ++下用Qt编写:
#include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); *// Important * QPushButton hello("Hello world!"); hello.resize(100, 30); hello.show(); return app.exec(); *// Important *}
Qml中的代码可能如下所示:
Item { function factorial(a) { a = parseInt(a); if (a <= 0) return 1; else return a * factorial(a - 1); } MouseArea { anchors.fill: parent onClicked: console.log(factorial(10)) } }
这些组件可以动态创建。
QML也有一个大型的类型系统,当在Typescript中定义所有这些类型时 ,无疑将非常有用。
您还可以轻松自定义组件:
Reactangle { id: redRectId width: 50 color: red }
几乎是CSS,不是吗?
Qt在大多数平台上可以做的就是要添加的所有内容。
我们将拥有Node.js
当搜索“ nodejs + qt”时,我们将立即获得node-qt ,但它立即引起人们的注意:该产品早已失效,并且上一次出现生命迹象是在8年前。
不过,在搜索中您可以找到一个非常新鲜的项目-NodeGui。
NodeGui
像Gui的许多库一样,Qt使用其事件/消息循环来处理来自小部件的事件。 因此,当我们有条件地调用app.exec()时,Qt将启动消息循环并将其阻塞在那里。 当整个应用程序中只有一个消息循环时,所有这些都很好。 但是,由于我们需要将Qt与NodeJ一起使用,并且后者还具有自己的事件循环,因此不可能如此轻松地集成它们。 但是已经做出了这样的决定,例如,与Electron或yode捆绑在一起。 这些解决方案各有特点,它们至少引发两个进程-主线程和渲染器。 尽管如此,这种方法还是有很大的收获,不需要修改NodeJ或Chromium。
在使用NodeGui的情况下,情况略有不同,每个事物都有一个进程,因此,无需弄乱进程之间的事件。 为此,Nodejs被派生了,并且对Qt中必需的活页夹进行了较小的改进。 现在,您不需要像通常的node main.js一样启动进程,而是像qode main.js一样启动进程。 幸运的是,qode在@ nodegui / qode包中作为npm模块发布。 为了开始一个简单的问候世界,您需要安装一些软件包,有关每种操作系统的更多详细信息,请参见官方网站: https : //docs.nodegui.org/docs/guides/getting-started
默认情况下,在nodegui中,所有内容都是小部件,可以将它们固定在各种模板上。 当前,nodegui中有两种类型的模板:FlexLayout和QGridLayout。
Nodegui中的样式
目前,您可以内联和通过styleSheet设置小部件的样式。
widget.setInlineStyle(`color: green`) view.setStyleSheet(` `#helloLabel { color: red; padding: 10px; } #worldLabel { color: green; padding: 10px; } #rootView { background-color: black; } `);
默认情况下,Qt支持所有CSS2选择器( https://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types )
如果没有用于样式化组件的自定义属性,它也不是没有。 幸运的是,此类属性已在Qt的扩展坞中进行了描述,并在stackoverflow上进行了介绍。
*QPushButton* { qproperty-iconsize: 20px 20px; }
角度的
该项目的作者已经实现了反应支持,但是当然,每个人都忘记了Angular的存在。
如开始时所写,Angular可以使用大多数平台,但是到目前为止,还没有用于桌面的平台。 由于精心设计和结构化的Angular API,Angular下的nodegui的实现归结为使用Renderer编写自定义platformBrowserDynamic并将其替换为应用程序。
但是,这一切如何由内而外起作用?
我们有条件的main.ts,我们将从它开始。
引导过程包括两个部分:创建平台和将启动模块放入其中。
platformBrowserDynamic().bootstrapModule(AppModule);
通过createPlatformFactory,我们可以创建您需要的任何平台。 对我们来说,这意味着我们不想使用普通的DOM,此外,在处理渲染时,我们将详细介绍元素的交互方案。 可在源代码中找到有关创建平台的更多信息。
在启动模块中,我们描述了首先渲染哪个组件。 创建组件实例时,Angular会调用renderComponent
并将其与该组件实例接收的所需渲染关联。 Angular在组件渲染方面所做的一切(创建元素,设置属性,订阅事件等)都将通过此渲染器。 因此,我们需要替换RendererFactory。
首先,在Renderer中,我们将对createElement方法感兴趣。 在此方法中,我们获得标签的名称,然后需要从中创建所需的组件。 幸运的是,nodegui有一组基本的组件,我仔细移植并描述了它们将如何在Angular框架中呈现,并将所有内容都放入了常规组件目录中。 使用标准组件的其他操作也将通过此渲染器。 更多细节 。
https://blog.nrwl.io/
要在渲染器中侦听事件,将抛出事件的名称,对于这些组件,我们将挂起通常的eventListener。
listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void { const callbackFunc = (e: NativeEvent) => callback.call(target, e); target.addEventListener(eventName, callbackFunc); return () => target.removeEventListener(eventName, callbackFunc); }
例如,组件事件与Qt完全相同,而不是通常的(click)=”clickFunc($event)”
您必须编写(clicked) = ”clickFunc($event)”
。
当前有16个标准组件可用。 但是,如果您需要编写自定义组件,那么总是有机会通过QWidget进行此操作。
还制作了一个路由器,以使我们的应用程序与Angular尽可能兼容。
const appRoutes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'about', component: AboutComponent } ]; // AppModule imports ... NodeguiRouterModule.forRoot(appRoutes),

Angular Nodegui应用

天气应用
我们收集产品
为了构建现成的应用程序,nodegui拥有自己的@nodegui/packer.
器- @nodegui/packer.
该实用程序非常简单,到目前为止由2个团队组成。
npx nodegui-packer-初始化myapp
此命令将创建一个包含模板的打包文件夹。 您可以更改内容以添加图标,更改应用程序的名称,描述和其他信息,以及添加必要的依赖项。
npx nodegui-packer-打包
此命令启动打包所需的工具(例如,macdeployqt for mac)并打包依赖项。
总结
总之,我想将结果与台式机上的其他Web解决方案进行比较(在Mac OS下启动的结果)。
下载大小
内存使用
链接到项目:
irustm /角节点
*使用Angular构建高性能,本机和跨平台的桌面应用程序。 Angular NodeGUI由Angular提供支持
有关项目的信息:
https://t.me/ngFanatic
有关我的开源项目的信息
https://twitter.com/irustm