章节内容
历史介绍
开发环境
代码封装
函数式
获取小说命令行版(上)
获取小说命令行版(中)
获取小说命令行版(下)
嵌入到应用中
插件机制
文字转语音
设置与信号中断
插件商店
下载与删除(上)
下载与删除(下)
通知栏程序
播放功能
美化界面
数据可视化(上)
数据可视化(中)
数据可视化(下)
嵌入到应用中
打包应用

以类的形式封装只是演示,只是一种思路,并非在后续会使用,但是大家可以参考在自己的项目中使用。这里面有一些坑,我会告诉你,我其实也尝试过 TypeScript 的方式,最终还是败给了错误。假如你想要使用 class 封装,那么一定要注意生命周期。

# 安装一些常用库

npm install electron-util camelcase --save
  • electron-util 里面封装了常用的帮助库

  • camelcase 是用来转事件名的,改成驼峰式命名

这里告诉大家  快速搜索包的一个小技巧,下载 chrome 右键搜插件,自行添加 npm 搜索设置然后就可以选中包明进行快速搜索。

# 添加事件映射

添加 main/events.js

export default [
  'accessibility-support-changed',
  'activate',
  'activity-was-continued',
  'before-quit',
  'browser-window-blur',
  'browser-window-created',
  'browser-window-focus',
  'certificate-error',
  'continue-activity',
  'gpu-process-crashed',
  'login',
  'new-window-for-tab',
  'open-file',
  'open-url',
  'quit',
  'ready',
  'select-client-certificate',
  'update-activity-state',
  'web-contents-created',
  'will-continue-activity',
  'will-finish-launching',
  'will-quit',
  'window-all-closed'
]

里面存放的是所有需要转换到 app 上面的事件 ,等会我们会让它们自动做绑定。

# Application.js

导入依赖

import electron from 'electron'
import util from 'electron-util'
import camelcase from 'camelcase'
import events from './events'

构造函数里面第一个要准备的是 ready 事件,只有当这个事件都完成的时候,才能继续做一些事情,假如你想直接把 electron 上面的东西通过 Object.assign 拷贝到 this 上面,会报错,因为没有准备好,能拷贝某些模块也会报错。 electron 上面的属性其实是一些 getter。

绑定 ready 的时候不要忘记绑定 this,要不然 this 会丢失,这是 js 的陷阱之一。

class Application {
  constructor() {
    electron.app.on('ready', this.ready.bind(this))
  }
}

然后在 ready 里面创建窗口和初始化事件绑定

async ready() {
  Object.assign(this, electron)
  this.mainWindow = this.createMainWindow()
  this.initEvent()
}

创建窗口,要做一些兼容,使用 util 会简洁不少,比如判断环境载入不同的开始文件。

  createMainWindow(opts) {
    const win = new electron.BrowserWindow(opts)

    if (util.is.development) {
      win.webContents.openDevTools()
      win.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`)
    } else {
      util.loadFile(win, 'index.html')
    }

    win.on('close', () => {
      this.mainWindow = null
    })

    win.webContents.on('devtools-opened', () => {
      win.focus()
      setImmediate(() => win.focus())
    })

    return win
  }

初始化事件,假如自身没有这个方法的时候不要绑定,要不然绑个 undefined 会报错

  initEvent() {
    events.forEach(name => {
      if (this[camelcase(name)]) {
        this.app.on(name, this[camelcase(name)].bind(this))
      }
    })
  }

添加个平台兼容事件,这两个是事件,在 initEvent 里面会自动绑定。

  windowAllClosed() {
    if (util.is.macos) {
      electron.app.quit()
    }
  }

  activate() {
    if (!this.mainWindow) {
      this.mainWindow = this.createMainWindow()
    }
  }

这样我们就实现了一个约定优先的 Electron 开发框架,只要你封装的够好,完全可以实现一个快速开发框架。

# 入口文件

修改 main/index.js, 够刚刚的类进行实例化。

import Application from './Application'

let app = new Application()

# 避免循环依赖

在编程中,对于初学者最头疼的可能就是循环依赖了,假如你有一个 Tray.js 来控制通知栏的一些逻辑,建议在 ready 里面实例化,并把this传递进去,这样不仅可以避免循环依赖,还可以避免有些逻辑没有准备好,导致的错误。

import Tray from './tray'
async ready() {
  this.tray = new Tray(this)
}

另外一种方式就是属性注入。

let app = new Application()
electron.app.on('ready', () => {
  app.tray = new Tray()
  app.tray.app = app
})

或者使用一个依赖管理中心

const depHub = {}
let app = new Application(depHub)
electron.app.on('ready', () => {
  let tray = new Tray(depHub)
  depHub.app = app
  depHub.tray = tray
})

代码在这里