angular2创建应用
by William Boxx
威廉·博克斯(William Boxx)
如何使用Angular和SQLite3创建Electron应用程序。 (How to create an Electron app using Angular and SQLite3.)
I was recently experimenting with converting one of my Angular web apps into a desktop application using Electron. I encountered a few hurdles along the way, and decided to put my experience in writing so that it may help others. If you have similar plans for your project, I hope this may be of use. The source code for this guide can be found here.
我最近正在尝试使用Electron将我的Angular Web应用程序之一转换为桌面应用程序。 在此过程中,我遇到了一些障碍,因此决定将自己的经验用于写作,以便对他人有所帮助。 如果您对项目有类似的计划,我希望这可能会有用。 该指南的源代码可以在这里找到。
第一部分:角度 (Part I: Angular)
创建样板。 (Create the Boilerplate.)
For the sake of this guide, we will be creating a new Angular app from scratch. I will be using Electron-Forge to create the boilerplate. Electron-Forge offers several templates for creating boilerplate code, including one for Angular 2. First install the Electron-Forge CLI.
为了本指南,我们将从头开始创建一个新的Angular应用。 我将使用Electron-Forge创建样板。 Electron-Forge提供了几个模板来创建样板代码,其中一个模板用于Angular2。首先安装Electron-Forge CLI。
$ npm i -g electron-forge
Now use the CLI to create the Angular app boilerplate.
现在,使用CLI创建Angular应用样板。
$ electron-forge init electron-angular-sqlite3 --template=angular2$ cd electron-angular-sqlite3
The forge CLI will add the bare essentials we need to run our app. Let’s add a few additional directories to house our database files. Add an assets directory under src, and put data and model directories under it.
伪造的CLI将添加运行我们的应用程序所需的基本知识。 让我们添加一些其他目录来容纳我们的数据库文件。 在src下添加资产目录,并在其下放置数据和模型目录。
$ mkdir ./src/assets/data ./src/assets/model
The directory tree should now look like this:
现在,目录树应如下所示:
.+-node_modules+-src| || +-assets| | || | +-data| | +-model| || +-app.component.ts| +-bootstrap.ts| +-index.html| +-index.ts|+-.compilerc+-.gitignore+-package-lock.json+-package.json+-tsconfig.json+-tslint.json
写一些代码。 (Write Some Code.)
As our first step, let’s add a model file that we will match our database schema. For this simple example, let’s create a class called Item. Each item will contain an id and a name property. Save the file in your project at src/assets/model/item.schema.ts
.
作为第一步,让我们添加一个与数据库模式匹配的模型文件。 对于这个简单的示例,让我们创建一个名为Item的类。 每个项目将包含一个id和一个name属性。 将文件保存在您的项目中,位于src/assets/model/item.schema.ts
。
We will be using TypeORM for our object relational mapping. First install TypeORM.
我们将使用T ypeORM进行对象关系映射。 首先安装TypeORM。
$ npm install typeorm --save
We will be following the TypeORM guide for creating schema here. When finished the file should look like this:
我们将在此处遵循TypeORM 指南来创建架构。 完成后,文件应如下所示:
TypeORM makes use of typescript decorators. We use the Entity decorator to declare our Item class a table. The @PrimaryGeneratedColumn()
decorator declares id
as our unique identification and tells the database to automatically generate it. We will worry about linking to a database later on.
TypeORM使用Typescript 装饰器 。 我们使用Entity装饰器将Item类声明为一个表。 @PrimaryGeneratedColumn()
装饰器将id
声明为我们的唯一标识,并告诉数据库自动生成它。 稍后我们将担心链接到数据库。
创建服务。 (Create the Service.)
Our next likely action would be to create an app service that handles communication from the front to the back end. Electron makes available the IpcRenderer
class for just this thing. IpcRenderer
is Electron’s inter process communication class that is used in the renderer process. Basically, we want to use the IpcRenderer
to send messages to Electron’s main process. These messages will pass information to the main process so that it can handle the database interactions.
我们下一个可能的操作是创建一个应用程序服务,以处理从前端到后端的通信。 Electron仅为此提供IpcRenderer
类。 IpcRenderer
是在渲染器进程中使用的Electron的进程间通信类 。 基本上,我们想使用IpcRenderer
将消息发送到Electron的主进程。 这些消息会将信息传递给主进程,以便它可以处理数据库交互。
Implementing the IpcRenderer
is where we come across our first hurdle. Electron is relying on the window.require() method, which is only available inside of Electron’s renderer process. This is a well documented issue. To get around this, we can use ThornstonHans’ ngx-electron package, which wraps all the Electron API’s exposed to the renderer process into a single Electron Service. You can read more about this here.
实现IpcRenderer
是我们遇到的第一个障碍。 Electron依赖window.require()方法,该方法仅在Electron的渲染器过程内部可用。 这是一个有据可查的问题 。 为了解决这个问题,我们可以使用ThornstonHans的ngx-electron软件包,该软件包将暴露给渲染器进程的所有Electron API封装到一个Electron服务中。 您可以在此处了解更多信息。
Before we can use ngx-electron
, we need to install it.
在使用ngx-electron
,我们需要先安装它。
$ npm install ngx-electron --save
Now let’s create a service to handle our IpcRenderer
communication. Create src/app.service.ts
.
现在,让我们创建一个服务来处理我们的IpcRenderer
通信。 创建src/app.service.ts
。
In app.service.ts
we create a class calledAppService
and add the @Injectable()
decorator. This allows us to use angular’s built in dependency injection (DI). In our constructor, we create a local variable _electronService
of type ElectronService
. The ElectronService
class is provided to us by ngrx-electron
. It allows us to use Electron’s IpcRender
class without any of the aforementioned issues.
在app.service.ts
我们创建一个名为AppService
的类,并添加@Injectable()
装饰器。 这使我们可以使用angular的内置依赖项注入(DI)。 在我们的构造函数中,我们创建一个类型为ElectronService
的局部变量_electronService
。 ElectronService
类由ngrx-electron
提供给我们。 它使我们可以使用Electron的IpcRender
类,而不会出现任何上述问题。
We create three functions: one that get’s all Items in the database, one to add an Item to the database, and one to delete an Item. Each function will return an Observable.
我们创建了三个函数:一个在数据库中获取所有Item,一个将一个Item添加到数据库中,另一个删除一个Item。 每个函数将返回一个Observable。
Observables are part of the RxJs Library and provide a good way of handling our database interactions asynchronously. You can read more about Observables here. Note the use of the Observable operator of
to denote that we are wrapping our response from this._electronService.ipcRenderer.sendSync()
as an Observable value.
可观察对象是RxJs库的一部分,并提供了一种异步处理我们的数据库交互的好方法。 您可以在此处阅读有关Observables的更多信息。 注意使用可观察的运营商of
表示,我们正在从包装我们的Reactthis._electronService.ipcRenderer.sendSync()
作为可观察到的值。
注册服务和编写组件。 (Registering Services and Writing Component.)
With our service complete, let’s go into src/app.component.ts
and register it for DI. While in there, we will add a simple html template and functions to handle our button events.
完成我们的服务后,让我们进入src/app.component.ts
并将其注册为DI。 在此处,我们将添加一个简单的html模板和函数来处理按钮事件。
Make sure to add AppService
as a provider in the @NgModule
decorator arguments and also as a private variable in the AppComponent
constructor. We also need to add ElectronService
as a provider.
确保在@NgModule
装饰器参数中将AppService
添加为提供程序,并在AppComponent
构造函数中添加为私有变量。 我们还需要将ElectronService
添加为提供程序。
On initialization of our component, we want to load all contents of our database and display it. To do this, we subscribe to the addItem()
function of the service we created. If you remember, all of our service functions return Observables. To get data from our observable, we subscribe to it, passing a callback function that runs when the data is received. In the example above, (items) => (this.itemList = ite
ms) will populate our class variable itemL
ist with the contents of the database once it is retrieved.
在初始化组件时,我们要加载数据库的所有内容并显示它。 为此,我们订阅了我们创建的服务的addItem()
函数。 如果您还记得,我们所有的服务功能都将返回Observables。 为了从可观察对象获取数据,我们订阅了它,并传递了一个回调函数,该函数在接收到数据时运行。 在上面的示例中, (items) => (this.itemList = ite
ms)一旦检索到数据库,就会使用数据库的内容填充我们的类le itemL
ist。
We follow similar tactics for adding and deleting items from the database. Each time repopulating itemList
with the updated contents of the database.
我们遵循类似的策略从数据库中添加和删除项目。 每次用数据库的更新内容重新填充itemList
。
第二部分:电子 (Part II: Electron)
安装SQLite3。 (Installing SQLite3.)
Now that we finished up our front end, we need to create the Electron backend. The Electron backend will handle and process messages sent from the front and manage the sqlite3 database.
现在我们完成了前端,我们需要创建Electron后端。 Electron后端将处理和处理从前端发送的消息,并管理sqlite3数据库。
We will be using sqlite3 for our database and need to install it.
我们将对数据库使用sqlite3并需要安装它。
$ npm install sqlite3 --save
A hurdle I ran into while working with sqlite3 and Electron initially, was that sqlite’s native binaries need to be recompiled for use with Electron. Electron-Forge should take care of this for you. One thing to note, Electron-Forge will use node-gyp to compile the binaries. You may need to have it properly installed and configured prior to use, which includes installing Python. As of now, node-gyp uses python 2. If you have multiple versions on your machine, you must ensure that current build is using the proper one.
最初在使用sqlite3和Electron时遇到的一个障碍是,需要重新编译sqlite的本机二进制文件才能与Electron一起使用。 Electron-Forge应该为您解决这个问题。 需要注意的一件事是,Electron-Forge将使用node-gyp来编译二进制文件。 您可能需要在使用之前正确安装和配置它,包括安装Python。 到目前为止 ,node-gyp使用python2。如果您的计算机上有多个版本,则必须确保当前版本使用的是正确的版本。
连接到数据库。 (Connecting to the Database.)
Now let’s open our src/index.ts
file and add some code to connect to the database. The two things we need to do are, connect to the database, and add functions to handle our requests from the renderer process. The finished file looks like this:
现在,让我们打开src/index.ts
文件,并添加一些代码以连接到数据库。 我们需要做的两件事是,连接到数据库,并添加函数来处理来自渲染器进程的请求。 完成的文件如下所示:
An in depth explanation of TypeORM and Electron is beyond the scope of this guide, so I will only briefly discuss the above file. First we need to import the createConnection
class from the TypeORM library. We also need to import or Item schema.
对TypeORM和Electron的深入说明超出了本指南的范围,因此,我仅简要讨论上述文件。 首先,我们需要从TypeORM库中导入createConnection
类。 我们还需要导入或项目架构。
As expected, the createConnection
class will create a connection to our database. We pass it a constructor with parameters such as type, database, and entities. Type is a string that describes what type of database we are using. Database is a string that points to the database location. Entities is where we tell TypeORM what schemas to expect. For our purpose: type is ‘sqlite’, Database is ‘./src/assets/data/database.sqlite’, and Entities is our imported Item class.
如预期的那样, createConnection
类将创建到我们数据库的连接。 我们将参数,类型,数据库和实体的构造函数传递给它。 Type是一个字符串,描述我们正在使用的数据库类型。 数据库是指向数据库位置的字符串。 实体是我们告诉TypeORM期望的模式的地方。 出于我们的目的:类型是“ sqlite”,数据库是“ ./src/assets/data/database.sqlite”,而实体是我们导入的Item类。
TypeORM allows you two options when working with database transactions: EntityManager and Repository. Both will give you access to functions for querying the database, without writing the SQL. We create a Repository object with the line itemRepo = connection.getRepository(Item)
. This gives us access to transaction methods for our Item table.
在处理数据库事务时,TypeORM有两个选项: EntityManager和Repository 。 两者都将使您无需编写SQL即可访问用于查询数据库的函数。 我们使用行itemRepo = connection.getRepository(Item)
创建一个Repository对象。 这使我们可以访问Item表的事务处理方法。
The last step is to create functions to handle the messages being sent from the IpcRenderer
. Each function will use the itemRepo
object we created to access the database. After successful completion of each transaction, the functions will pass the new state of the database back to the renderer.
最后一步是创建函数来处理从IpcRenderer
发送的消息。 每个函数将使用我们创建的itemRepo
对象来访问数据库。 成功完成每个事务后,这些函数会将数据库的新状态传递回渲染器。
第三部分:运行! (Part III: Run it!)
With everything complete, we can now run the app. Electron-Forge handles this process for us. All we need to do is run the command:
一切完成后,我们现在可以运行该应用程序。 Electron-Forge为我们处理此过程。 我们需要做的就是运行命令:
$ npm run start
If everything is correct, Electron will open your app and you can test it out.
如果一切正确,Electron将打开您的应用,您可以对其进行测试。
Thanks for reading!
谢谢阅读!
翻译自: https://www.freecodecamp.org/news/creating-an-electron-app-using-angular-and-sqlite3-24ca7d892810/
angular2创建应用