electron+vue开发项目总结

3,163 阅读4分钟

前言

大前端技术真的是无所不能,可以使用React Nativeuni-app技术做App应用、可以使用nodejs实现后端服务。有一个桌面软件应用的项目需求,C++人手不足,遂决定让我们前端用electron技术来承接该桌面软件应用,没有electron使用经验,开发过程中遇到诸多问题,此篇文章总结记录遇到的问题及解题方式。

项目搭建

electron官方文档中给我们提供了demo案例代码 electron/electron-quick-start,我们把它从github上拉下来执行。 要使用vue开发页面,我们需要创建electron+vue的项目,使用vue-cli-plugin-electron-builder,只需要四部就可新建一个electron+vue的项目:

  1. vue-cli创建一个vue项目 vue create electron-vue
  2. 进入项目目录安装electron npm install --save-dev electron
  3. 安装依赖包vue-cli-plugin-electron-builder
  4. 执行命令 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创建出来的一个个窗口,而非每新建一个页面就是新建了一个渲染进程。

图片.png 渲染进程使用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怎么去实现这个功能呢? 20210907_165132.gif 悬浮小球,本质上也是通过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: {
                  oneClickfalse,  //是否创建一键安装程序或辅助
                  allowElevationtrue,  // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
                  allowToChangeInstallationDirectorytrue,  // 允许修改安装目录,建议为 true,是否允许用户改变安装目录,默认是不允许
                  installerIcon'build/icons/icon.ico',  // 安装时的图标
                  uninstallerIcon'build/icons/icon.ico',
                  installerHeaderIcon'build/icons/icon.ico',
                  createDesktopShortcuttrue,  //是否创建桌面快捷方式
                  createStartMenuShortcuttrue  //是否创建开始菜单快捷方式
                }
            }
        }
    }
}