关于electron:如何用Vue开发Electron桌面程序-干货分享

21次阅读

共计 8070 个字符,预计需要花费 21 分钟才能阅读完成。

一、Electron 介绍


Electron 是一个由 GitHub 及泛滥贡献者组成的沉闷社区独特保护的开源我的项目. 应用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序

1. 特点

  • 跨平台 能够打包成 Mac、Windows 和 Linux 三个平台的应用程序
  • 简化桌面端开发(1)Electron 基于 Chromium 和 Node.js, 能够应用 HTML, CSS 和 JavaScript 构建利用(2)提供 Electron api 和 NodeJS api
  • 社区沉闷

2. 兼容性

xp 无缘了, 可能须要应用 nwjs 等计划

二、我的项目搭建

1. 应用 vue cli 创立 vue 我的项目

vue create electron-test
复制代码

2. 装置插件 vue-cli-plugin-electron-builder

vue add electron-builder
复制代码

3. 装置完插件后, 我的项目中的一些变动

① package.json 新增了几个 scripts

npm run electron:serve  electron 开发模式
npm run electron:build   electron 打包
复制代码

postinstall 和 postuninstall 是为了确保装置或者移除依赖时, 始终跟 electron 匹配

② 新增了 background.js 文件

主过程相干操作, 写在这个文件中

③ 新增了一个环境变量

能够用来判断是否在 electron 状态

process.env.IS_ELECTRON
复制代码

三、开发总结

1. 配置我的项目图标

应用electron-icon-builder, 生成合乎 Electron 的图标

① 装置

npm install --save-dev electron-icon-builder
复制代码

package.json 中配置生成命令

"electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten"
复制代码

③ 生成图标

npm run electron:generate-icons
复制代码

④ 应用

import path from 'path'
const win = new BrowserWindow({icon: path.join(__static, 'icon.png')
})
复制代码

2. 我的项目开发模式运行呈现 Failed to fetch extension 正告

因为网络问题, 开发模式无奈下载 vue devtool 导致的正告, 须要在 background.js 中正文掉下载代码

3. 我的项目应用本地的 vue devtools

① 首先能够将 vue devtools 的代码 clone 下来, 而后进行编译

git clone https://github.com/vuejs/vue-devtools.git
cd vue-devtools
npm install
npm run build
复制代码

而后把 vue-devtools/packages/shell-chrome 文件夹复制到我的项目根目录

② 在 background.js 文件的 app.on('ready', 生命周期中进行加载

// 应用本地的 vue 开发者工具
session.defaultSession.loadExtension(path.resolve('shell-chrome'))
复制代码

③ 创立窗口的时候应用上面示例办法, 即可失常显示出 vue 开发者工具

// src/background.js
if (process.env.WEBPACK_DEV_SERVER_URL) {
  await transferWin.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '/#/test')
  if (!process.env.IS_TEST) transferWin.webContents.openDevTools()} else {transferWin.loadURL('app://./index.html' + '/#/test')
}
复制代码

4. 渲染过程中如何应用 NodeJS api

须要在 vue.config.js 中配置 nodeIntegration 为 true

module.exports = {
  pluginOptions: {
    electronBuilder: {nodeIntegration: true}
  }
}
复制代码

或者在创立窗口时配置

win = new BrowserWindow({
    width: 500,
    height: 400,
    frame: false,
    transparent: true,
    backgroundColor: '#00000000', // 当敞开开发者工具时, 会从新创立一个新的渲染视图, 所以会应用配置的背景色彩, 如果没配置会应用默认值红色
    webPreferences: {
      nodeIntegration: true, // 渲染层能够应用 node
      webSecurity: false, // 跨域
      enableRemoteModule: true // 能够应用 remote
    },
    // eslint-disable-next-line no-undef
    icon: path.resolve(__static, 'logo.png')
  })
复制代码

5. 让创立的窗口能够跨域

创立窗口的时候配置 webSecurity: false即可

6. 如何监听窗口的状态, 最小化, 聚焦, 窗口暗藏, 窗口显示, 窗口敞开

// 窗口最小化触发
win.on('minimize', () => {console.log('最小化')
})
win.on('focus', () => {console.log('聚焦')
})
// 窗口暗藏, 任务栏没有图标
win.on('hide', () => {console.log('暗藏')
})
win.on('show', () => {flashTray(false)
  console.log('显示')
})
复制代码

7. 如何创立托盘图标

let tray = null
function createTray () {tray = new Tray(path.resolve(__static,‘logo.png’)) // 设置托盘图标
  const contextMenu = Menu.buildFromTemplate([
     new MenuItem({
      label: '退出程序',
      click: () => {
        isQuit = true
        app.exit()}
    })
  ])
  tray.setContextMenu(contextMenu) // 设置右键菜单
  tray.on(‘click’, () => { // 托盘点击事件
    if (win.isVisible()) {win.focus()
    } else {win.show()
    }
  })
}
复制代码

监听主窗口的敞开, 如果不是齐全退出,

则只是暗藏窗口

win.on('close', e => {if (isQuit) {win = null} else {e.preventDefault()
      win.hide()}
})
复制代码

8. 托盘闪动与任务栏闪动

① 托盘闪动原理就时定时的切换托盘的图标, 图标与透明图标的切换

let flashInterval
function flashTray (bool) {if (!bool) {flashInterval && clearInterval(flashInterval)
    tray.setImage(path.resolve(__static, 'logo.png'))
    return
  }
  flashInterval && clearInterval(flashInterval)
  var count = 0
  flashInterval = setInterval(function() {if (count++ % 2 == 0) {tray.setImage(path.resolve(__static, 'empty.png'))
    } else {tray.setImage(path.resolve(__static, 'logo.png'))
    }
  }, 400)
}
复制代码

② 任务栏的闪动

win.flashFrame(true) // 高亮
复制代码

9. 如何只运行单个实例

如果你的程序是利用的次要实例并且当 app.requestSingleInstanceLock()返回 true 时,你应该持续让你的程序运行。如果当它返回 false,

那就立刻退出

const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {app.quit()
} {app.on('second-instance', (event, argv) => {if (process.platform === 'win32') {if (win) {if (win.isMinimized()) {win.restore()
        }
        if (win.isVisible()) {win.focus()
        } else {win.show()
        }
      }     }
  })
}
复制代码

10. 主过程与渲染过程如何通信

参考文档:

ipcMain ipcRenderer

① 渲染过程

const {ipcRenderer} = require('electron')
ipcRenderer.send('message', 'ping') // 发送给主过程
ipcRenderer.on('message-reply', (event, arg) => {console.log(arg) // pong
}
复制代码

主过程

// 监听渲染过程信息
ipcMain.on('message', (event, arg) => {console.log('ping')
  event.sender.send('message-reply', 'pong') // 回复子程序
})
// 主过程独自往渲染过程发信息
win.webContents.send('message-reply', 'pong')
复制代码

11. 打包问题

应用 nsis 打包 windows 程序的安装包 在 vue.config.js 中配置打包

配置

module.exports = {
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        win: {target: [{ target: 'nsis', arch: ['ia32', 'x64'] }]
        },
        nsis: {
          oneClick: false, // 一键装置
          perMachine: true, // 为所有用户装置
          allowElevation: true, // 容许权限晋升, 设置 false 的话须要从新容许安装程序
          allowToChangeInstallationDirectory: true, // 容许更改装置目录
          createDesktopShortcut: true, // 创立桌面图标
          createStartMenuShortcut: true, // 创立开始菜单
          deleteAppDataOnUninstall: true,
          include: './public/nsis/installer.nsh', // 蕴含的脚本
          guid: '53fe4cba-120d-4851-3cdc-dccb3a469019' // 软件 guid
        }
      }
    }
  }
}
复制代码

12. 从网页关上程序

① 主过程注册

app.removeAsDefaultProtocolClient(‘testapp’)
app.setAsDefaultProtocolClient(‘testapp’)
复制代码

② 在 nsis 打包配置文件 (installer.nsh) 中增加配置 在装置的时候在注册表注册 URL protocol

!macro customInstall
  DetailPrint 'Register testapp URI Handler'
  DeleteRegKey HKCR 'testapp'
  WriteRegStr HKCR 'testapp' '''URL:testapp'
  WriteRegStr HKCR 'testapp' 'URL Protocol' ''WriteRegStr HKCR'testappshell''' ''WriteRegStr HKCR'testappshellOpen''' ''WriteRegStr HKCR'testappshellOpencommand''' '$INSTDIR${APP_EXECUTABLE_FILENAME} %1'
!macroend
复制代码

③ 间接在浏览器拜访链接即可触发关上客户端 testapp://? 参数 = 值

④ 获取网页端传来的参数

// window 零碎中执行网页调起利用时,解决协定传入的参数
const handleArgvFromWeb = (argv) => {console.log(argv)
  const url = argv.find(v => v.indexOf(`${URLSCHEME}://`) !== -1)
  console.log(url)
  if (url) handleUrlFromWeb(url)
}
// 进行解决网页传来 url 参数,参数自定义,以下为示例
// 示例调起利用的 url 为 testapp://?token=205bdf49hc97ch4146h8124h8281a81fdcdb
const handleUrlFromWeb = (urlStr) => {console.log(urlStr)
  const urlObj = new URL(urlStr)
  const {searchParams} = urlObj
  const token = searchParams.get('token')
  console.log(token)
}
复制代码

能够看到获取的参数是个数组, 咱们就时要获取最初一项

生产模式下, 如果软件没有提前关上, 通过网页开启时, 须要依照下图形式来获取参数

若提前开启, 则在判断单例的条件判断中获取

13. 装置依赖或打包时呈现 electron 包下载过慢问题

根目录创立 .npmrc 文件

registry = https://registry.npm.taobao.org
 
sass_binary_site = https://npm.taobao.org/mirrors/node-sass/
phantomjs_cdnurl = http://cnpmjs.org/downloads
electron_mirror = https://npm.taobao.org/mirrors/electron/
sqlite3_binary_host_mirror = https://foxgis.oss-cn-shanghai.aliyuncs.com/
profiler_binary_host_mirror = https://npm.taobao.org/mirrors/node-inspector/
chromedriver_cdnurl = https://cdn.npm.taobao.org/dist/chromedriver
复制代码

14. 通过里面浏览器关上链接

const {shell} = require('electron')
shell.openExternal('https://www.bing.com')
复制代码

15. 开发模式如果关上窗口时, 若开启了开发者工具, 想敞开窗口, 须要先把开发者工具敞开, 能力失常敞开窗口

在窗口敞开前, 判断开发者工具是否开启, 若开启则先敞开开发者工具, 例如

if (callWin.isDevToolsOpened()) {callWin.closeDevTools()
}
复制代码

16. 通明无边框窗口, 接触到屏幕边缘会呈现彩色边框问题

次要就是创立窗口时增加延

时,

setTimeout(() => createWindow(), 400)
复制代码

而后敞开硬件加速

app.disableHardwareAcceleration()
app.commandLine.appendSwitch('disable-gpu')
app.commandLine.appendSwitch('disable-software-rasterizer')
复制代码

17. 通明无边框窗口, 当敞开开发者工具时, 背景会变红色问题

当敞开开发者工具时, 会从新创立一个新的渲染视图, 所以会应用配置的背景色彩, 如果没配置会应用默认值红色 所以须要在窗口创立时设置 backgroundColor 属性为#00000000

18. 渲染过程获取主过程环境变量

const {remote} = require('electron')
const envData = remote.getGlobal('process').env
复制代码

19. 打包时, 报错 asar 文件被占用

vscode 能够再 setting.json 里配置疏忽 dist_electron 文件夹

"files.exclude": {"dist_electron": true,}
复制代码

20. 软件更新

应用electron-updater

① 配置 vue.config.js 设置publish 配置, 配置了这个配置后, 打包后会生成一个 latest.yml 文件, 须要将其和安装包放在服务器同一目录下, url配置成服务器能够拜访到这个目录的 url, 也能够应用 autoUpdater.setFeedURL(url) 动静配置 url

pluginOptions: {
  electronBuilder: {
    builderOptions: {
      publish: [
        {
          provider: 'generic',
          url: 'http://127.0.0.1:5000'
        }
      ]
    }
  }
}
复制代码

21. electron win7 问题

① win7 sp1 or win8 needed install KB4019990 patch to resolve this issue for now(note:none sp1 win7 needed to upgrade to sp1 before install the patch)须要装置补丁解决黑屏问题

② 降级.net

③ 敞开硬件加速

22. 7z 解压 asar 插件

目前我用 asar 命令行解压会报错, 然而用 7z 的插件尽管报错, 却能够残缺解压 插件地址: https://www.tc4shell.com/en/7…

下载好, 把 dll 复制到 7z 装置目录下新建一个 Formats 文件夹中

正文完
 0