前言
大前端技术真的是无所不能,可以使用React Native、uni-app技术做App应用、可以使用nodejs实现后端服务。有一个桌面软件应用的项目需求,C++人手不足,遂决定让我们前端用electron技术来承接该桌面软件应用,没有electron使用经验,开发过程中遇到诸多问题,此篇文章总结记录遇到的问题及解题方式。
项目搭建
electron官方文档中给我们提供了demo案例代码 electron/electron-quick-start,我们把它从github上拉下来执行。 要使用vue开发页面,我们需要创建electron+vue的项目,使用vue-cli-plugin-electron-builder,只需要四部就可新建一个electron+vue的项目:
- vue-cli创建一个vue项目
vue create electron-vue - 进入项目目录安装electron
npm install --save-dev electron - 安装依赖包
vue-cli-plugin-electron-builder - 执行命令
vue add electron-builder
tips:在安装的过程中,可能会非常的慢,我们可以选择使用国内镜像,配置国内镜像有两种方式可供选择:
1. 全局配置,通过npm命令更改下载源
- 全局设置下载源
npm config set registry https://npm.taobao.org/mirrors/node - 设置node源码加速
npm config set disturl https://npm.taobao.org/mirrors/node - 更改electron镜像
npm config set ELECTRON_MIRROR https://npm.taobao.org/mirrors/electron/
2. 在项目中根目录添加配置文件
在项目根目录新建文件 .npmrc 文件,添加如下代码
registry=https://registry.npm.taobao.org/
disturl=https://npm.taobao.org/mirrors/node
ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron
主进程和渲染进程
主进程:每个应用都有一个主进程,主进程是应用的入口,它运行在完整的Nodjs环境中,我们可以在主进程文件中书写任何nodejs的代码,它可以直接对原生系统进行操作
渲染进程:关于渲染进程的概念,本人在此处有一点疑问,因此在此处只提出疑问,希望大佬们给予解答。
查阅网上大佬们的文章,说每新建一个页面就是一个新的渲染进程,那使用electron+vue,是否是每新建一个路由页面就意味着创建了一个新的渲染进程呢?
文档上有一句是说在主进程中通过使用BrowserWidnow这个模块来创建一个窗口,在单独的进程(即渲染进程)中显示网页内容。
我个人的理解渲染进程是BrowserWindow创建出来的一个个窗口,而非每新建一个页面就是新建了一个渲染进程。
渲染进程使用nodejs
主进程可以书写任何nodejs代码,在实际项目中,我们需要在页面文件中也可以书写nodejs代码,我们只需要在创建窗口,根据官方api配置 nodeIntegration:true 即可
主进程与渲染进程通信
在页面上点击关闭按钮退出应用,或者拖拽页面移动使得窗口随鼠标移动。这样的需求场景,需要主进程与渲染进程进行通信,渲染进程发送一个消息,主进程监听到该消息后做相应逻辑处理。electron提供了两个API,用于主进程的ipcMain和用于渲染进程的ipcRenderer
// 渲染进程发送一个事件
doment.addEventListener('mousemove',(e)=>{
ipcRenderer.send('move-suspend',{
baseX:e.screenX,
baseY:e.screenY
})
})
// 主进程中监听它
ipcMain.on('move-suspend', (event, args) => {
const workAread = screen.getPrimaryDisplay().workArea
if (args.baseX < workAread.width - 100 && args.baseY < workAread.height - 100) {
suspendWin && suspendWin.setPosition(args.baseX, args.baseY)
}
})
全屏窗口
我们知道新创建窗口的时候,我们可以给窗口设置宽高。现在我们需要创建一个和电脑屏幕一样大小的窗口,我们很容易想到获取电脑屏幕的宽高,将其给到窗口的宽高配置
const bounds = screen.getPrimaryDisplay().bounds
new BrowserWindow({
width:bounds.width,
height:bounds.height
})
如上代码,screen.getPrimaryDisplay()获取到屏幕的阵列信息,通过它获取到屏幕的宽高、位置等信息
全屏透明窗口
全屏窗口的设置没有什么问题,现在又需要做一个全屏的透明窗口。在上面基础上,添加配置属性transparent:true,本以为这样就ok了,但是运行发现,会是黑屏。找了许久不知道为啥会造成黑屏,但是我们只需要再给窗口设置fullscreen:true即可达到全屏透明窗口
实现悬浮小球
做桌面软件,产品可能会要求在桌面右下角悬浮一个窗口,可以通过这个窗口快捷进入某些功能页面中。我们可以通过electron怎么去实现这个功能呢?
悬浮小球,本质上也是通过
BrowserWindow创建出来的一个窗口,该窗口的配置参数如下:
let ballWin = new BrowserWindow({
width:150, // 窗口的宽度
height:150, // 窗口的高度
resizable:false, // 不可改变大小
transparent:true, // 窗口设为透明
alwaysOnTop:true, // 总是置顶
frame:false, // 无窗口框
webPreferences:{
nodeIntegration:true // 渲染进程可用nodejs
}
})
ballWin.setSkipTaskbar(true) // 任务栏不显示它
ballWin.loadURL(process.env.WEBPACK_DEV_SERVER_URL) // 此处是你页面的路由地址,自行填写
创建一个悬浮小球就是这么简单,创建好窗口后,你只需要在你的页面上布局写样式,然后添加与主进程交互的代码就ok了,渲染进程js代码如下:
const { ipcRenderer } = require('electron')
let isDown = false
let baseX = 0
let baseY = 0
const ball: any = this.$refs.ball
document.addEventListener('mousedown', function (e) {
isDown = true
baseX = e.x
baseY = e.y
document.addEventListener('mousemove', moveEvent)
})
document.addEventListener('mouseup', function () {
isDown = false
})
function moveEvent (e) {
if (isDown) {
ipcRenderer.send('move-suspend', {
baseX: e.screenX - baseX,
baseY: e.screenY - baseY
})
}
}
这种悬浮小球功能,形态上可能与通常的窗口页面不同,但是本质上还是与常见的窗口页面写法思路一样
打包问题
项目做完了,我们需要将其打包成桌面应用,electron官方文档为我们推荐了electron-builder工具,它是一个完备的Electron应用打包和分发解决方案,它可以将我们的项目打包成mac、windows、linux的应用程序安装包。它这么强大,那么我们如何使用它呢? 翻阅它的官方文档 electron-builder,我们可以在package.json文件中添加"build"对象属性来进行配置,如:
"build": {
"appId": "xxx",
"dmg":{},
"nsis":{}
}
如上在package.json中配置是一种方式,在该项目中,我使用的是在vue.config.js中添加打包配置,在vue.config.js中的pluginOptions对象属性中,添加关于electron-builder的配置项
// vue.config.js
module.exports = {
pluginOptions:{
electronBuilder:{
builderOptions:{
win: {
icon: 'build/icons/icon.ico',
target: [
{
target: 'nsis',
arch: ['x64']
}
]
},
nsis: {
oneClick: false, //是否创建一键安装程序或辅助
allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
allowToChangeInstallationDirectory: true, // 允许修改安装目录,建议为 true,是否允许用户改变安装目录,默认是不允许
installerIcon: 'build/icons/icon.ico', // 安装时的图标
uninstallerIcon: 'build/icons/icon.ico',
installerHeaderIcon: 'build/icons/icon.ico',
createDesktopShortcut: true, //是否创建桌面快捷方式
createStartMenuShortcut: true //是否创建开始菜单快捷方式
}
}
}
}
}