likes
comments
collection
share

Vue 结合Electron使用

作者站长头像
站长
· 阅读数 17

Electron是什么

Electron 是一个跨平台的、基于 Web 前端技术的桌面 GUI (图形化)应用程序开发框架。你可以使用 HTML、CSS 来绘制界面和控制布局,使用 JavaScript 来控制用户行为和业务逻辑,使用 Node.js 来通信、处理音频视频等,几乎所有的 Web 前端技术和框架(jQuery、Vue、React、Angular 等)都可以应用到桌面 GUI 开发中,可简单的理解为给已有的图形界面进行套壳打包为桌面端的开发框架。

Electron如何在vue中使用

安装

electron在vue中有两种安装方式:

  1. 直接安装electron
npm install electron --save-dev

2.安装集成好的vue-electron

npm install vue-electron --save

安装时可能出现的问题:

  1. Npm i electron 等待时间长,不成功,可使用cnpm安装即可
  2. 权限问题可直接使用sudo,但之后打包都需要使用sudo,也可直接修改文件权限,这里不做赘述

background.js

安装完成后在项目下会自动生成background.js文件,并且可在package.json中看到自动添加了main: background.js(main属性指定了程序的主入口文件),并且package.json也可看到运行的指令:

"electron:build": "vue-cli-service electron:build", (生产打包桌面端)

"electron:serve": "vue-cli-service electron:serve", (开发环境运行)

background.js中有很多的配置,具体的配置则看官方即可:www.electronjs.org/zh/docs/lat…

需要注意的是new BrowserWindow为创建window窗口,还有就是配置electron菜单:

app.on('ready', async () => {

  // @ts-ignore

  const menu = Menu.buildFromTemplate(menuList);

  Menu.setApplicationMenu(menu);

  if (isDevelopment && !process.env.IS_TEST) {

    // Install Vue Devtools

    try {

      await installExtension(VUEJS_DEVTOOLS);

    } catch (e) {

      // @ts-ignore

      console.error('Vue Devtools failed to install:', e.toString());

    }

  }

  createWindow();

});

menuList菜单配置可自行修改,配置方式参考:codeup.aliyun.com/sevenfiftee…

到这里electron的安装运行则已经完成了

Electron在线更新

在线更新主要是可迭代和可修改,不需要向用户重复的发安装包,可先应用中更新,在线更新使用到electron-updater插件

工作原理

首先我们来看一下electron大致的工作原理,使用electron-updater插件是如何进行升级的,如下图:

Vue 结合Electron使用

大致上是:electron通过electron-updater对请求服务器上的latest.yml文件,进行对比本地的latest.yml文件,latest.yml文件中有版本号和安装包位置的信息,对比后发现版本不一致则进行更新下载安装包,覆盖本地的文件并重新安装,一般情况下安装包和latest.yml放在一起,这样就不需要修改latest.yml文件信息,latest.yml文件为打包后生成的:

version: 0.0.1

files:

  - url: 砼库管理后台_setup_0.0.1.zip

    sha512: eUGBD5XYRKSvENU77LanmfmOdTebvvI0xtkyJDs/lLhX7UqyrZxWFyKFG+Dh4Bt+Ej/U5d/IH7atcZpXLLnXxQ==

    size: 83400869

  - url: 砼库管理后台_setup_0.0.1.dmg

    sha512: 1+oMlCGnPcI35YTpneEZRkhwss+pj6cI1Odpq5BYrqlACwfwEe/dklnavEqi6aYwchGqA80gB1drxFfoEY8fCA==

    size: 86389963

path: 砼库管理后台_setup_0.0.1.zip

sha512: eUGBD5XYRKSvENU77LanmfmOdTebvvI0xtkyJDs/lLhX7UqyrZxWFyKFG+Dh4Bt+Ej/U5d/IH7atcZpXLLnXxQ==

releaseDate: '2021-11-10T13:48:30.850Z'

如何实现

首先latest.yml不会直接生成需要在vue.config.js中添加,主要是publish,其他的配置看官网即可,详细配置如下:

pluginOptions: {

    electronBuilder: {

      builderOptions: {

        productName: '砼库管理后台',

        appId: 'com.tongku.www',

        directories: {

          output: 'dist'

        },

        publish: [

          {

            provider: 'generic',

            url: ''

          }

        ],

        mac: {

          icon: 'build/icons/icon.icns',

          artifactName: '${productName}_setup_${version}.${ext}'

        },

        win: {

          icon: 'build/icons/icon.ico',

          target: ['nsis', 'zip'],

          artifactName: '${productName}_setup_${version}.${ext}'

        },

        nsis: {

          oneClick: false,

          perMachine: true,

          allowElevation: true,

          allowToChangeInstallationDirectory: true,

          installerIcon: '../build/icons/icon.icns',

          uninstallerIcon: '../build/icons/icon.icns',

          installerHeaderIcon: '../build/icons/icon.icns',

          createDesktopShortcut: true,

          createStartMenuShortcut: true

        }

      },

      nodeIntegration: true

    }

  }

添加后打包会发现出现latest.yml文件(mac为latest-mac.yml),这里mac打包时需要注意,因为apple的限制,在线更新时需要有对应用进行签名,这里不做赘述可直接参考(segmentfault.com/a/119000001…

updater.ts

对更新使用到的方法进行封装,ipcMain为electron中通讯使用的方式,

autoUpdater.checkForUpdates();为对比latest.yml是否需要更新

autoUpdater.downloadUpdate()为下载安装包

autoUpdater.quitAndInstall()为重启并安装新的安装包

import { autoUpdater } from 'electron-updater';

import { ipcMain } from 'electron';

let mainWindow: any = null;



export function updateHandle(window, feedUrl) {

  mainWindow = window;

  const message = {

    error: '检查更新出错',

    checking: '正在检查更新……',

    updateAva: '检测到新版本,正在下载……',

    updateNotAva: '现在使用的就是最新版本,不用更新'

  };

  // 设置更新包的地址

  autoUpdater.autoDownload = false;

  autoUpdater.setFeedURL(feedUrl);

  // 监听升级失败事件

  autoUpdater.on('error', (error) => {

    sendUpdateMessage({

      cmd: 'error',

      message: error

    });

  });

  // 监听开始检测更新事件

  autoUpdater.on('checking-for-update', (message) => {

    sendUpdateMessage({

      cmd: 'checking-for-update',

      message

    });

  });

  // 监听发现可用更新事件

  autoUpdater.on('update-available', (message) => {

    sendUpdateMessage({

      cmd: 'update-available',

      message

    });

  });

  // 监听没有可用更新事件

  autoUpdater.on('update-not-available', (message) => {

    sendUpdateMessage({

      cmd: 'update-not-available',

      message

    });

  });



  // 更新下载进度事件

  autoUpdater.on('download-progress', (progressObj) => {

    sendUpdateMessage({

      cmd: 'download-progress',

      message: progressObj

    });

  });

  // 监听下载完成事件

  autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName, releaseDate, updateUrl) => {

    sendUpdateMessage({

      cmd: 'update-downloaded',

      message: {

        releaseNotes,

        releaseName,

        releaseDate,

        updateUrl

      }

    });

  });

  // 检查更新

  autoUpdater.checkForUpdates();



  // 重启安装

  ipcMain.on('quitAndInstall', () => {

    autoUpdater.quitAndInstall(false, true);

  });

  // 执行更新检查

  ipcMain.on('checkUpdate', () => {

    autoUpdater.checkForUpdates();

  });

  // 手动下载更新文件

  ipcMain.on('confirmDownloadUpdate', () => {

    autoUpdater.downloadUpdate();

  });

}

// 给渲染进程发送消息

function sendUpdateMessage(text) {

  console.log(text);

  mainWindow.webContents.send('message', text);

}

app.vue中调用updater.ts中的方法进行更新:

public mounted() {

      this.getIsUpdate();

  }



  private update() {

    if (this.percent !== 100) {

      ipcRenderer.send('confirmDownloadUpdate');

    } else {

      ipcRenderer.send('quitAndInstall');

      this.$refs.progressModal.closeModal();

    }

  }

  private getIsUpdate() {

    // 接收主进程版本更新消息

    ipcRenderer.on('message', (event, arg) => {

      console.log(arg);

      if ('update-available' === arg.cmd) {

        // 显示升级对话框

        this.$nextTick(() => {

          this.$refs.progressModal.showModal();

        });

      } else if ('download-progress' === arg.cmd) {

        console.log(arg.message.percent);

        this.percent = Math.round(parseFloat(arg.message.percent));

      } else if (arg.cmd === 'update-downloaded') {

        this.percent = 100;

        this.$message.success('更新成功');

      }

    });

    ipcRenderer.send('checkUpdate');

    // 间隔1小时检测一次

    const interval = window.setInterval(() => {

      ipcRenderer.send('checkUpdate');

    }, 60 * 60 * 1000);

  }

至此electron的使用和在线更新已经完成了✿✿ヽ(°▽°)ノ✿