Electron学习笔记

378 阅读4分钟
  • 技术架构

    • Chromium - Chrome浏览器内核
    • Node.js
    • Native apis - 系统api
  • 生命周期事件

    • ready:app初始化完成
    • dom-ready:一个窗口中的文本加载完成
    • did-finish-load:导航完成时触发
    • window-all-closed:所有窗口都被关闭时触发(如果监听了该事件需要手动调用app.quit()方法才可以关闭app)
    • before-quit:在关闭窗口之前触发
    • will-quit:在窗口关闭并且应用退出时触发
    • quit:当所有窗口被关闭时触发
    • closed:当窗口关闭时触发,此时应删除窗口引用
  • 使用nodemon命令可以实现监听和动态刷新

"scripts": {
  "start": "nodemon --watch main.js --exec npm run build",
  "build": "electron ."
},
  • 通过配置BrowserWindow的show属性可以解决页面白屏问题
const mainWindow = new BrowserWindow({
  show: false,
  width: 800,
  heigh: 400
})
mainWindow.on('ready-to-show', () => {
  mainWindow.show()
})
  • 窗口属性
    • resizable:是否允许拉伸窗口
    • minHeight/Width:最小高度/宽度
    • maxHeight/Width:最大高度/宽度
    • title:窗口标题
    • icon:窗口图标
    • frame:是否包含窗体操作栏
    • reansparent:透明窗体
    • autoHideMenuBar:是否隐藏菜单栏

electron12.0.0版本废弃了remote,需要使用@electron/remote进行替代

  • 设置以下属性可以让渲染进程也可以使用require
// BrowserWindow配置
webPreferences: { 
    nodeIntegration: true,
    contextIsolation: false,
    enableRemoteModule: true
}
  • 渲染进程使用electron相关的API,必须使用remote获取:

  • 主进程初始化开启模块,其中mainWindow为主窗口实例

require('@electron/remote/main').initialize() 
require("@electron/remote/main").enable(mainWindow.webContents)
  • 渲染进程中引入
const {BrowserWindow}=require('@electron/remote')
  • 使用remote可以获取当前窗口
const { BrowserWindow, getCurrentWindow } = require('@electron/remote')
getCurrentWindow()
  • 可以使用Menu来实现自定义菜单
const { Menu } = require('electron')
const template = [
  {label: 'file', 
   icon: './xx.png' // 定制菜单图标
   accelerator: 'ctrl + o', // 定义快捷键
   click() {
  	... // 定义点击菜单的处理事件
   }
  },
  ...
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
  • 打开外部链接
const { shell } = require('electron')
await shell.openExternal('https://electronjs.org')
  • 获取当前运行系统平台的类型
const isMac = process.platform === 'darwin' // 是否为Mac系统
  • 实现右键点击菜单
// renderer
window.addEventListener('contextmenu', (e) => {
  e.preventDefault()
  ipcRenderer.send('show-context-menu')
})

ipcRenderer.on('context-menu-command', (e, command) => {
  // ... 
})

// main
ipcMain.on('show-context-menu', (event) => {
  const template = [
    {
      label: 'Menu Item 1',
      click: () => { event.sender.send('context-menu-command', 'menu-item-1') }
    },
    { type: 'separator' },
    { label: 'Menu Item 2', type: 'checkbox', checked: true }
  ]
  const menu = Menu.buildFromTemplate(template)
  menu.popup({ window: 		BrowserWindow.fromWebContents(event.sender) }) // 在当面窗口弹出菜单
})
  • 主进程和渲染进程间的通信

  • 渲染进程向主进程发送消息

const { ipcRenderer } = require('electron') // 必须引入的模块
// 渲染进程
ipcRenderer.send('xtom', "一条来自渲染进程的消息!")
const returnValue = ipcRenderer.sendSync('xtoms', "一条来自渲染进程的同步消息!")

// 主进程
ipcMain.on('xtom', (ev, data) => {
  ev.sender.send('xtomRe', '一条来自主进程的回复内容!')
})

ipcMain.on('xtoms', (ev,  data) => {
  ev.returnValue = '一条来自主进程的同步回复内容!'
})
  • 主进程向渲染进程发送消息
// 主进程
BrowserWindow.getFocusedWindow().webContents.send('mtox', '一条来自主进程的消息!')
 
// 渲染进程
ipcRenderer.on('mtox', (ev, data) => {
  console.log(ev, data);
}) 
  • 渲染进程间通信

    • 使用localStorage或者其他数据存储方案进行数据存储和读取
    • 渲染进程发送消息到主进程,主进程再发送消息到指定的(可以 通过id获取winodw对象)渲染进程
    • 如果要在打开新窗口的 同时发送消息,可以直接使用生产的window对象,但是要在监听到window.webContents.on('did-finish-load')之后发送消息
  • 打开web开发者调试工具(方便调试)

mainWindow.webContents.openDevTools()
  • 开启文件选择窗口
const { dialog } = require('@electron/remote')

dialog.showOpenDialog({
  defaultPath: __dirname,
  properties: ['openFile', 'multiSelections'],
  filters: [
    { name: 'js代码', extensions: ['js'] }
  ]
}).then((ret) => {
  console.log(ret); 
})
  • shell:使用默认应用程序来管理文件和URL
shell.openExternal(e.target.getAttribute('href')) // 打开URL
shell.showItemInFolder(path.resolve(__filename))  // 显示文件
shell.openPath(path.resolve(__filename))	// 打开文件
  • 全局快捷键的注册和移除
// 注册
globalShortcut.register('ctrl + command + o', () => {
  console.log("快捷键注册成功");
})
// 移除 - 如果不移除将一直生效 
globalShortcut.register('ctrl + command + o')
globalShortcut.unregisterAll()
  • 剪切板的使用
const ret = clipboard.writeText('test')
clipboard.readText(ret)

// 复制图片的时候使用nativeImage
const image = nativeImage.createFromPath('./msg.png')
const imgRet = clipboard.writeImage(image)
const nImg clipboard.readText()
conts imgDom = new Image()
imgDom.src = nImage.toDataURL()
document.body.appendChild(imgDom)
  • 项目开发时需要使用到的支持库
    • electorn-is-dev - 判断electron是否为开发环境
    • concurrently - 连接多个命令,命令用双引号包裹,空格分割
    • wait-on - 等待前一个命令的执行完成后,执行后一个命令
    • cross-env - 跨平台的配置环境变量,控制编译后的网页内容不在浏览器中展示
// package.json
"scripts":{
	"ele": "concurrently \"cross BROWSER=none yarn start\" \"wait-on http://locahost:3000 && elect ron .\""
}    
  • 在前端(非node环境下)代码中node模块,需要使用window.xx可以进行引入调用
// helper.js
const fs = window.require('fs').promises

// react or vue文件
import { xx, xxx} from './utils/helper'
cost path = window.require('path')
  • Electron store可以实现数据持久化

  • Electron中,除main.js外,其他js操作均处于渲染进程

PS:如果有需要补充的内容,请在评论区留言

转载时请注明“来自掘金 - EvenZhu”