原来,electron自动更新是这样的

引言
在Electron应用程序中,窗口管理和自动更新是两个关键特性,它们对用户体验和应用程序的可靠性至关重要。在本篇文章中,我们将探讨如何在Electron应用程序中有效地管理窗口,以及如何实现自动更新机制。

1. 窗口管理
Electron应用程序通常由多个窗口组成,如主窗口、对话框、弹出窗口、登录窗口等。有效地管理这些窗口对于创建一个流畅的用户界面至关重要。

创建窗口

在Electron中,我们直接使用BrowserWindow类来创建窗口。你可以设置窗口的各种属性,如大小、位置、图标等,下面是一个简单例子。

// 主进程中的代码
const { app, BrowserWindow } = require('electron');
function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });
  // 加载页面或文件
  win.loadFile('index.html');
  // 打开开发者工具(如果需要)
  // win.webContents.openDevTools();
  // 处理窗口关闭事件
  win.on('closed', () => {
    win = null;
  });
}
app.whenReady().then(createWindow);

窗口事件

窗口支持多种事件,如closedmovedresized等。你可以监听这些事件来响应窗口的各种状态变化。

窗口间通信

窗口之间可以通过ipcMainipcRenderer进行通信。这允许你在主进程和渲染进程之间,或者在不同渲染进程之间传递数据。

以下是我封装了一个window的示例,用于登录窗口切换主窗口:

// window.js
import { app, BrowserWindow, globalShortcut, ipcMain } from 'electron'
import { join } from 'path'
import { buildMenu } from './menu'
import { createTray } from './tray'
import icon from '../../resources/icon.png?asset'
import { checkForUpdates } from './updater'

// 快捷键注册
function registryShortcut() {
  globalShortcut.register('CommandOrControl+K', () => {
    // 获取当前窗口,并注册快捷键
    BrowserWindow.getFocusedWindow().webContents.openDevTools()
  })
}

let loginWindow
let mainWindow

// 创建窗口的公共方法
function createWindow(config, url) {
  const baseConfig = {
    show: false,
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      webSecurity: false,
      // nodeIntegration: true, // 根据需要设置
      // contextIsolation: false, // 根据需要设置
      devTools: true
    }
  }

  if (process.platform === 'linux') {
    baseConfig.icon = icon
  }

  const finalConfig = { ...baseConfig, ...config }
  const win = new BrowserWindow(finalConfig)

  if (!app.isPackaged && process.env['ELECTRON_RENDERER_URL']) {
    win.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    win.loadFile(url)
  }

  win.once('ready-to-show', () => win.show())

  return win
}

// 创建登录窗口
function createLoginWindow() {
  loginWindow = createWindow(
    {
      width: 600,
      height: 670,
      autoHideMenuBar: true
    },
    join(__dirname, '../renderer/index.html')
  )

  // 加载 /login 路由
  loginWindow.webContents.on('did-finish-load', () => {
    loginWindow.webContents.send('replace', '/login')
  })

  ipcMain.once('login', () => {
    loginWindow.close()
    createMainWindow()
  })
}

// 创建主窗口
function createMainWindow() {
  mainWindow = createWindow(
    {
      width: 1024,
      height: 768,
      autoHideMenuBar: false
    },
    join(__dirname, '../renderer/index.html')
  )

  ipcMain.once('open-window', () => {
    createMainWindow()
  })

  ipcMain.once('logout', () => {
    mainWindow.close()
    createLoginWindow()
  })

  // 检查更新
  ipcMain.on('checkUpdate', () => {
    checkForUpdates(mainWindow, ipcMain)
  })

  // 主要用于创建顶部窗口导航栏
  buildMenu(mainWindow)
  // 托盘
  createTray(mainWindow)
}

app.whenReady().then(() => {
  createLoginWindow()
  // 注册快捷键
  if (!app.isPackaged && process.env['ELECTRON_RENDERER_URL']) {
    registryShortcut()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createLoginWindow()
  }
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

export default {
  createLoginWindow,
  createMainWindow
}

2. 自动更新

自动更新是保持应用程序最新和安全的常用方法。Electron提供了electron-updater库来实现自动更新机制。

使用electron-updater

首先,你需要安装electron-updater库。

npm install electron-updater

然后,在主进程中初始化electron-updater,并配置更新选项。

// 主进程中的代码
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const { autoUpdater } = require('electron-updater');
function createWindow() {
  // ...创建窗口的代码
}
app.whenReady().then(createWindow);
// 设置自动更新
autoUpdater.on('update-available', (info) => {
  dialog.showMessageBox({
    type: 'info',
    title: '更新可用',
    message: '有新的更新可用,是否下载并安装?',
    button: ['是', '否']
  }).then((result) => {
    if (result.response === 0) {
      autoUpdater.downloadUpdate();
    }
  });
});
autoUpdater.on('update-downloaded', (info) => {
  dialog.showMessageBox({
    type: 'info',
    title: '更新下载完成',
    message: '更新已下载,是否重启以安装?',
    button: ['是', '否']
  }).then((result) => {
    if (result.response === 0) {
      autoUpdater.quitAndInstall();
    }
  });
});
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

下面提供了一个封装的demo

// update.js
import { app } from 'electron'
import { autoUpdater } from 'electron-updater'
import path from 'path'
import log from 'electron-log'
import { isNil, debounce } from 'lodash'

export function checkForUpdates(mainWindow, ipcMain) {
  autoUpdater.logger = log
  log.transports.file.level = 'debug'
  autoUpdater.autoDownload = false

  // 未打包时是开发环境
  // 用于本地调试
  if (!app.isPackaged) {
    Object.defineProperty(app, 'isPackaged', {
      get: () => true
    })
    autoUpdater.updateConfigPath = path.join(__dirname, '../../app-update.yml')
  }

  function sendUpdateMsg(statusObj) {
    mainWindow.webContents.send('updateStatus', statusObj)
  }

  autoUpdater.once('error', (error) => {
    const errMsg = isNil(error) ? 'unknown' : (error.stack || error).toString()
    sendUpdateMsg({
      status: 'error',
      msg: errMsg
    })
  })

  // 没有更新时触发
  autoUpdater.once('update-not-available', () => {
    sendUpdateMsg({
      status: 'latest',
      msg: '已是最新版本'
    })
  })

  // 有更新时触发
  autoUpdater.once('update-available', () => {
    sendUpdateMsg({
      status: 'update-available',
      msg: '有新版本可更新,是否现在更新?'
    })
  })

  // 下载完成
  autoUpdater.once('update-downloaded', () => {
    sendUpdateMsg({
      status: 'completed',
      msg: '下载完成,重启更新'
    })
  })

  //监听开始检测更新事件
  autoUpdater.once('checking-for-update', function () {
    sendUpdateMsg({
      status: 'checking',
      msg: '监听开始检测更新事件'
    })
  })

  // 下载进度,包含进度百分比、下载速度、已下载字节、总字节等
  autoUpdater.once(
    'download-progress',
    debounce(function (progress) {
      sendUpdateMsg({
        status: 'downloading',
        msg: progress
      })
    }, 3000)
  )

  ipcMain.once('downloadUpdate', (info) => {
    autoUpdater.downloadUpdate()
  })

  ipcMain.once('quitAndInstall', () => {
    autoUpdater.quitAndInstall()
  })

  autoUpdater.checkForUpdates()
}

那么, 我们如何在本地调试更新呢?

我们必须保证远程已经发布过一次包了,我使用的是github action发布,具体下一章会讲,我们要本地打包一次,我的window系统,所以依次执行

npm run build
npm run build:win

打包成功后,把dist目录下app-update.yml文件代码复制给根目录app-update.yml,如下图所示

然后,update.js文件增加这串代码

image.png

修改version版本(必须比当前版本低)

最后本地运行

npm run dev

源码地址: https://github.com/zjwmmx/electron-app

结语

通过本篇文章,你应该对Electron中的窗口管理和自动更新机制有了更深入的了解。我们学习了如何使用BrowserWindow类来创建和管理窗口,以及如何使用electron-updater来实现自动更新功能。

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值