资讯专栏INFORMATION COLUMN

Electron 实战桌面计算器应用

GeekQiaQia / 2403人阅读

摘要:在菜单中,我想点击子菜单打开一个网站,那么就可以用到方法,则会在默认浏览器中打开打包应用其实将程序打包成桌面应用才是比较麻烦的事。

前言

Electron 是一个搭建跨平台桌面应用的框架,仅仅使用 JavaScript、HTML 以及 CSS,即可快速而容易地搭建一个原生应用。这对于想要涉及其他领域的开发者来说是一个非常大的福利。

项目介绍

仓库地址:lin-xin/calculator

我这里通过 Electron 实现了仿 iPhone 的计算器,通过菜单可以切换横屏和竖屏,横屏有更多的运算。而对于 JavaScript 进行浮点数计算来说,精度丢失是个很大问题,所以我这里使用了第三方库 math.js 来解决这个精度的问题。
尽可能的实现了跟 iPhone 一样的运算:

1 + 2 × 3 = 7

3 += 6 (再按 = 等于 9)

0.1 + 0.2 = 0.3 (浮点数精度处理)


不过我下面并不是要讲计算器,而是用到的 Electron 的知识点。

生命周期

在主进程中通过 app 模块控制整个应用的生命周期。

当 Electron 完成初始化时触发 ready 事件:

app.on("ready", () => {
    // 创建窗口、加载页面等操作
})

当所有的窗口都被关闭时会触发 window-all-closed 事件:

app.on("window-all-closed", () => {
    if(process.platform !== "darwin"){
        app.quit();     // 退出应用
    }
})

在开发中发现,没有监听该事件,打包后的应用关闭后,进程还保留着,会占用系统的内存。

窗口

本来我们的 html 只显示在浏览器中,而 electron 提供了一个 BrowserWindow 模块用于创建和控制浏览器窗口,我们的页面就是显示在这样的窗口中。

创建窗口

通过关键字 new 实例化返回 win 对象,该对象有丰富的方法对窗口进行控制。

win = new BrowserWindow({
    width: 390,         // 窗口宽度
    height: 670,        // 窗口高度
    fullscreen: false,  // 不允许全屏
    resizable: false    // 不允许改变窗口size,不然布局就乱了啊
});
加载页面

窗口创建完是一片空白的,可以通过 win.loadURL() 来加载要显示的页面。

const path = require("path");
const url = require("url");

win.loadURL(url.format({    // 加载本地的文件
    pathname: path.join(__dirname, "index.html"),
    protocol: "file",
    slashes: true
}))

也可以直接加载远程链接 win.loadURL("http://blog.gdfengshuo.com");

菜单

桌面应用菜单栏是最常见的功能。Electron 提供了 Menu 模块来创建原生的应用菜单和 context 菜单,

const template = [                              // 创建菜单模板
    {
        label: "查看",
        submenu: [
            {label: "竖屏", type: "radio", checked: true},      // type 属性让菜单为 radio 可选
            {label: "横屏", type: "radio", checked: false},
            {label: "重载",role:"reload"},
            {label: "退出",role:"quit"},
        ]
    }
]

const menu = Menu.buildFromTemplate(template);  // 通过模板返回菜单的数组
Menu.setApplicationMenu(menu);                  // 将该数组设置为菜单

在子菜单中,通过点击竖屏或横屏来进行一些操作,那就可以给 submenu 监听 click 事件。

const template = [
    {
        label: "查看",
        submenu: [
            {
                label: "横屏"
                click: () => {              // 监听横屏的点击事件
                    win.setSize(670,460);   // 设置窗口的宽高
                }
            }
        ]
    }
]
主进程和渲染进程通信

虽然点击横屏的时候,可以设置窗口的宽高,但是要如何去触发页面里的方法,这里就需要主进程跟渲染进程之间进行通信。

主进程,可以理解为 main.js 用来写 electron api 的就是主进程,渲染进程就是渲染出来的页面。

ipcMain

在主进程中可以使用 ipcMain 模块,它控制着由渲染进程(web page)发送过来的异步或同步消息。

const {ipcMain} = require("electron")
ipcMain.on("send-message", (event, arg) => {
    event.sender.send("reply-message", "hello world")
})

ipcMain 监听 send-message 事件,当消息到达时可以调用 event.sender.send 来回复异步消息,向渲染进程发送 reply-message 事件,也可以带着参数发送过去。

ipcRenderer

在渲染进程可以调用 ipcRenderer 模块向主进程发送同步或异步消息,也可以收到主进程的相应。

const {ipcRenderer} = require("electron")
ipcRenderer.on("reply-message", (event, arg) => {
    console.log(arg);       // hello world
})

ipcRenderer.send("anything", "hello everyone");

ipcRenderer 可以监听到来自主进程的 reply-message 事件并拿到参数进行操作,也可以使用 send() 方法向主进程发送消息。

webContents

webContents 是一个事件发出者,它负责渲染并控制网页,也是 BrowserWindow 对象的属性。在 ipcMain 中的 event.sender,返回发送消息的 webContents 对象,所以包含着 send() 方法用于发送消息。

const win = BrowserWindow.fromId(1);        // fromId() 方法找到ID为1的窗口
win.webContents.on("todo", () => {
    win.webContents.send("done", "well done!")
})
remote

remote 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。在 Electron 中,有许多模块只存在主进程中,想要调用这些模块的方法需要通过 ipc 模块向主进程发送消息,让主进程调用这些方法。而使用 remote 模块,则可以在渲染进程中调用这些只存在于主进程对象的方法了。

const {remote} = require("electron")
const BrowserWindow = remote.BrowserWindow      // 访问主进程中的BrowserWindow模块

let win = new BrowserWindow();                  // 其他的跟主进程的操作都一样

remote 模块除了可以访问主进程的内置模块,自身还有一些方法。

remote.require(module)          // 返回在主进程中执行 require(module) 所返回的对象
remote.getCurrentWindow()       // 返回该网页所属的 BrowserWindow 对象
remote.getCurrentWebContents()  // 返回该网页的 WebContents 对象
remote.getGlobal(name)          // 返回在主进程中名为 name 的全局变量(即 global[name])
remote.process                  // 返回主进程中的 process 对象,等同于 remote.getGlobal("process") 但是有缓存
shell 模块

使用系统默认应用管理文件和 URL,而且在主进程和渲染进程中都可以用到该模块。在菜单中,我想点击子菜单打开一个网站,那么就可以用到 shell.openExternal() 方法,则会在默认浏览器中打开 URL

const {shell} = require("electron");
shell.openExternal("https://github.com/lin-xin/calculator");
打包应用

其实将程序打包成桌面应用才是比较麻烦的事。我这里尝试了 electron-packager 和 electron-builder。

electron-packager

electron-packager 可以将项目打包成各平台可直接运行的程序,而不是安装包。

先使用 npm 安装: npm install electron-packager -S

运行打包命令:

electron-packager ./ 计算器 --platform=win32 --overwrite --icon=./icon.ico

打包会把项目文件包括 node_modules 也一起打包进去,当然可以通过 --ignore=node_modules 来忽略文件,但是如果项目中有用到第三方库,忽略的话则找不到文件报错了。

正确的做法就是严格区分 dependencies 和 devDependencies,打包的时候只会把 dependencies 的库打包,而使用 cnpm 安装的会有一大堆 .0.xx@xxx 的文件,也会被打包,所以最好不要用 cnpm

electron-builder

electron-builder 是基于 electron-packager 打包出来的程序再做安装处理,将项目打包成安装文件。

安装:npm install electron-builder -S

打包:electron-builder --win

打包过程中,第一次下载 electron 可能会出现连接超时,可以使用 yarn 试试。还有 winCodeSign 和 nsis-resources 也可能会失败,可以参考 electron-builder/issues 解决。

总结

Electron 用起来还是相对容易的,可以创建个简单的桌面应用,只是打包的过程比较容易遇到问题,网上好像也有一键打包的工具,没尝试过。以上也都是基于 windows 7 的实践,毕竟没有 Mac 搞不了。

更多文章:linxin/blog

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85222.html

相关文章

  • Electron入门介绍

    摘要:进程主进程在里,运行里脚本的进程被称为主进程。渲染进程由于使用来展示页面,所以的多进程结构也被充分利用。当一个实例被销毁后,相应的渲染进程也会被终止。在,我们提供用于在主进程与渲染进程之间通讯的模块。 Github 系列文章地址笔者前两天心血来潮做了个MACOS下可以进行OCR图文识别的小工具,发现Electron 在1.x之后API发生了挺大的变化,估计也是我好久没碰了,所以打算把这...

    yunhao 评论0 收藏0
  • 翻译 | 摆脱浏览器限制的JavaScript

    摘要:在考虑宇航员的生命安全时,轻微的打嗝或者服务中断都会酿成生死事故。也许最大的挑战来自谷歌主导的简称。在最近的开发者峰会,以及今年的会议上,谷歌都为安排了大量讨论。由微软提供,是广受欢迎的编辑器,到月份已经获得了超过五百万用户。 译者:安冬 (沪江Web前端开发工程师)本文原创翻译,转载请注明作者及出处。原文地址:http://developer.telerik.com/... 技术世界...

    xfee 评论0 收藏0
  • electron 将pc端(vue)页面打包为桌面应用

    摘要:于是乎,就想着把自己写的这个小项目打包成桌面端,方面每次打开电脑就能看。然后继续运行,然后白屏习惯性的首次失败。。解决方法进入文件夹下的将其中的修改为相对路径。再次运行,成功将的项目,显示为桌面应用。总结至此,打包桌面端就这样完成了。 背景 showImg(https://segmentfault.com/img/bVYowg?w=1922&h=862); 最近在学习RxJS,平时边看...

    Dongjie_Liu 评论0 收藏0
  • electron桌面应用

    摘要:说起桌面应用,想必大家使用过的就已经海了去了。那么现在我们就来生成一个程序包吧最后生成的可执行程序出就现在了如下位置愉快的双击使用吧 说起桌面应用,想必大家使用过的就已经海了去了。什么暴风影音、QQ、skype之类的,早已不是新鲜事!不过大家有没有了解过如何编写一个桌面应用?历史上,我们都有哪些方式去编写桌面应用呢? 实际上,桌面应用的历史并不算久远,不去查找各种资料,仅凭记忆,我能想...

    wawor4827 评论0 收藏0

发表评论

0条评论

GeekQiaQia

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<