上一篇介绍了 Electron 的架构,今天来了解一下它到底有什么 API 供我们使用~
(图片来源:Electronvue开发实战1)
从图可以了解,主进程、渲染进程都各自有可以使用的 API,而有些两边皆可以使用,因为这些功能实在是太多了,接下来就只介绍一些常用的 API
主进程 API
这边介绍的 API 只有主进程能用,无法在渲染进程使用
app
app 操控整个应用程式的生命週期,常会用来监听与整个应用程式的重要事件
// main.jsconst { app } = require('electron')app.on('window-all-closed', function () { app.quit()})
event
ready
:完成初始化时触发window-all-closed
:所有视窗关闭时触发activate
:唤醒应用程式时触发(macOS)browser-window-created
:视窗被创建时触发browser-window-focus
:视窗被关注时触发browser-window-blur
:视窗被取消关注时触发method
app.quit()
:关闭所有视窗app.exit()
:退出所有视窗,不会询问用户app.whenReady()
:初始化后执行(回传 Promise
)app.hide()
:隐藏所有视窗(macOS)app.show()
:显示所有视窗(macOS)app.requestSingleInstanceLock()
:视窗是否成功锁定为单一视窗(回传 Boolean
)// main.jsconst { app } = require('electron')let myWindow = nullconst gotTheLock = app.requestSingleInstanceLock() // 锁定视窗,并记录回传值if (!gotTheLock) { // 开启第二个视窗时无法成功锁定,关闭视窗 app.quit()} else { // 开启第二个视窗时触发,将第一个视窗还原并关注 // 此事件为第一个视窗发出 app.on('second-instance', (event, commandLine, workingDirectory) => { if (myWindow) { if (myWindow.isMinimized()) myWindow.restore() myWindow.focus() } }) // 正常开启视窗,并储存实例 app.whenReady().then(() => { // 如果 createWindow 为 Promise,则需使用 than 或 async/await myWindow = createWindow() })}
BrowserWindow
BrowserWindow 用来建立一个视窗,有许多外观与功能的重要设定,也能监听每个视窗的相关事件
options - 建立视窗参数
// main.jsconst { BrowserWindow } = require('electron')const path = require('path')// 以下没特别注记即为预设值const win = new BrowserWindow({ width: 800, // 宽度 height: 600, // 高度 x: 0, // 左方偏移量,预设置中 y: 0, // 上方偏移量,预设置中 useContentSize: false, // 设定窗口宽高是否包含框架与 Menu minWidth: 0, // 最小宽度 minHeight: 0, // 最小高度 maxWidth: 1000, // 最大宽度,预设无限制 maxHeight: 1000, // 最大高度,预设无限制 resizable: true, // 可否调整视窗大小 movable: true, // 可否移动视窗 minimizable: true, // 可否最小化 maximizable: true, // 可否最大化 closable: true, // 可否点击关闭按钮 alwaysOnTop: false, // 视窗是否总是在顶部 fullscreen: false, // 视窗是否全萤幕显示 fullscreenable: true, // 可否将视窗全萤幕 Kiosk: false, // 视窗是否开启 Kiosk 模式 title: 'Electron', // 视窗标题 icon: './images/icon.png', // 视窗框架图示 show: true, // 是否显示视窗 frame: false, // 是否隐藏框架 与 Menu parent: null, // 父视窗 disableAutoHideCursor: false, // 视窗内是否隐藏鼠标 autoHideMenuBar: false, // 是否隐藏 Menu(按下 Alt 可显示) backgroundColor: '#FFF', // 背景颜色 hasShadow: true, // 视窗是否有阴影 opacity: 0, // 视窗初始不透明度 darkTheme: false, // 视窗是否使用深色模式 transparent: false, // 视窗是否透明(frame 为 true 才有作用) webPreferences: { devTools: true, // 是否开启 devtools nodeIntegration: false, // 渲染进程是否可访问 Node.js preload: path.join(__dirname, 'preload.js'), // preload.js 文件位置 enableRemoteModule: false, // 是否启用 remote 模块 zoomFactor: 1.0, // 窗口缩放係数 webSecurity: true, // 是否开启同源政策(关闭之后页面才可以打 API) webgl: true, // 是否启用 WebGL plugins: false, // 是否启用插件 experimentalFeatures: false, // 是否启用 Chromium 实验功能 backgroundThrottling: true, // 是否在背景运行 }})win.loadURL('https://github.com')
event
// main.jsconst { BrowserWindow } = require('electron')const win = new BrowserWindow()win.on('close', (e) => { // do something...})
close
:视窗将要关闭时触发blur
:视窗失去焦点时触发focus
:视窗获得焦点时触发show
:视窗显示时触发hide
:视窗隐藏时触发ready-to-show
:视窗可显示时触发maximize
:视窗最大化时触发unmaximize
:视窗退出最大化时触发minimize
:视窗退出最小化时触发restore
:视窗还原最小化时触发will-resize
:调整视窗大小前触发resize
:调整视窗大小时触发resized
:调整视窗大小后触发will-move
:移动视窗前触发move
:移动视窗时触发moved
:移动视窗后触发enter-full-screen
:视窗进入全萤幕时触发leave-full-screen
:视窗退出全萤幕后触发method - 直接调用
// main.jsconst { BrowserWindow } = require('electron')BrowserWindow.getAllWindows()
BrowserWindow.getAllWindows()
:获取一个包含所有视窗实例的阵列BrowserWindow.getFocusedWindow()
:获取正在关注的视窗实例BrowserWindow.fromId(id)
:获取指定 id 的视窗实例method - 操作实例
// main.jsconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ width: 800, height: 1500 })win.destroy()
win.destroy()
:销毁视窗,仅会发出 closed
事件win.close()
:关闭视窗win.show()
:显示视窗win.hide()
:隐藏视窗win.maximize()
:视窗最大化win.minimize()
:视窗最小化win.restore()
:视窗还原最小化win.setFullScreen(Boolean)
:设定视窗是否全屏win.setSize(width, height)
:设定视窗宽高win.setContentSize(width, height)
:设定视窗宽高(不含框架与 Menu)win.moveTop()
:将视窗移至最上面win.center()
:将视窗移至中间win.setPosition(x, y)
:设定视窗位置win.setTitle(title)
:设定标题win.flashFrame(Boolean)
:设定视窗是否闪烁win.loadURL(url)
:视窗载入该 urlwin.loadFile(filePath)
:视窗载入该档案win.reload()
:重新载入当前网页优化小技巧
这边官方提到两个开启视窗的优化小技巧
先将页面隐藏,等视窗读取完成时再将其显示出来// main.jsconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ show: false })win.once('ready-to-show', () => { win.show()})
将背景颜色设为与自己应用程式相近或一样的背景色// main.jsconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ backgroundColor: '#2e2c29' })win.loadURL('https://github.com')
webContents
webContents 跟 BrowserWindow
相当雷同,建立视窗后若需改变该视窗设定则可使用此方法,另外也有一些更细微的操作
method - 直接调用
// main.jsconst { webContents } = require('electron')webContents.getAllWebContents()
webContents.getAllWebContents()
:获取一个所有视窗的 Array
webContents.getFocusedWebContents()
:获取正在关注的视窗物件webContents.fromId(id)
:获取指定 id 的视窗物件method - 操作实例
// main.jsconst { BrowserWindow } = require('electron')const win = new BrowserWindow({ width: 800, height: 1500 })win.webContents.loadURL('http://github.com')
win.webContents.loadURL(url)
:视窗载入该 urlwin.webContents.loadFile(filePath)
:视窗载入该档案win.webContents.reload()
:重新载入当前网页win.webContents.reloadIgnoringCache()
:重新载入当前网页(忽略快取)win.webContents.getURL()
:获取当前网页网址win.webContents.getTitle()
:获取当前网页标题win.webContents.clearHistory()
:清除历史纪录win.webContents.goBack()
:上一页win.webContents.goForward()
:下一页win.webContents.goToIndex(index)
:导航到该索引索面win.webContents.getUserAgent()
:获取此网页用户代理win.webContents.getZoomFactor()
:获取当前缩放係数win.webContents.setZoomFactor(factor)
:设定缩放係数,原始为 1.0win.webContents.openDevTools()
:打开 devtoolswin.webContents.closeDevTools()
:关闭 devtoolswin.webContents.copy()
:複製win.webContents.cut()
:剪下win.webContents.paste()
:贴上win.webContents.undo()
:复原win.webContents.redo()
:重做win.webContents.capturePage([x, y, width, height])
:网页截图(回传 Promise
)win.webContents.send(channel, ...args)
:同 ipcMain.send
win.webContents.startDrag({file, icon})
:操作拖动文件win.webContents.printToPDF(options)
:将网页截图存成 PDF// main.jsconst { BrowserWindow } = require('electron')const fs = require('fs') // 档案操作const path = require('path') // 路径操作const os = require('os') // 系统操作const win = new BrowserWindow({ width: 800, height: 600 })win.loadURL('http://github.com')// loading 完成之后执行win.webContents.on('did-finish-load', () => { win.webContents.printToPDF({}).then(data => { // 设定路径为桌面上的 demo.pdf const pdfPath = path.join(os.homedir(), 'Desktop', 'demo.pdf') // 将档案创建在该路径 fs.writeFile(pdfPath, data, (error) => { if (error) throw error }) }).catch(error => { // catch error })})
Menu
Menu 用来建立与设定选单,可直接建立上方工具列的选单,或是其他地方的内容选单
method - 直接调用
// main.jsconst { Menu } = require('electron')const isMac = process.platform === 'darwin'// 设定 Menu 样板(Windows 与 MacOS 分开设定)const template = [ ...(isMac ? [{ label: 'A-Menu', submenu: [ { role: 'quit' } ] }] : [{ label: 'B-Menu', submenu: [ { role: 'undo' }, { type: 'separator' }, { label: '关闭', role: 'quit' } ] }])]// 用样板建立一个选单const menu = Menu.buildFromTemplate(template)// 设定应用程式顶部选单Menu.setApplicationMenu(menu)
Menu.buildFromTemplate(template)
:建构一个选单实例Menu.setApplicationMenu(menu)
:设定顶部选单method - 操作实例
// main.jsconst { ipcMain, BrowserWindow, Menu } = require('electron')ipcMain.on('click-right', () => { // 设定 Menu 样板 const template = [ { label: 'B-Menu', submenu: [ { role: 'undo' }, { type: 'separator' }, { label: '关闭', role: 'quit' } ] } ] // 用样板建立一个选单 const menu = Menu.buildFromTemplate(template) // 显示弹出选单 menu.popup(BrowserWindow.getFocusedWindow())})
menu.popup([options])
:显示弹出选单menu.closePopup([browserWindow])
:关闭弹出选单menu.append(menuItem)
:将 menuItem
插入选单最后方menu.insert(pos, menuItem)
:将 menuItem
插入指定位置建立选单 template
可以参考官方文件
优化小技巧
如果想要客製化自己的 Menu,可以将 Menu 隐藏,并自己使用刻一个,不过要让自己的视窗可以拖拉记得加上 CSS 属性 -webkit-app-region: drag
,但是不要覆盖到功能按钮,否则按钮会失效
<div class="menu"> <div class="drag"> <img class="icon" src="./icon.png"> <span>title</span> </div> <button><img class="icon" src="./minimiz.png"></button> <button><img class="icon" src="./maximiz.png"></button> <button><img class="icon" src="./close.png"></button></div>
.drag { -webkit-app-region: drag;}
Tray
Tray 是右下角的图示与功能,使用 Menu
建立选单,须于初始化后调用
event
// main.jsconst { Tray } = require('electron')const tray = new Tray()tray.on('click', (e) => { // do something...})
click
:图示选单被左键点击时触发right-click
:图示选单被右键点击时触发double-click
:图示选单被双击时触发method
// main.jsconst { app, Menu, Tray } = require('electron')let tray = nullapp.whenReady().then(() => { // 设定 icon 路径 const tray = new Tray('./images/icon.png') // 设定选单样板 const contextMenu = Menu.buildFromTemplate([ { label: 'Item1', click: () => { console.log('click') } }, { label: 'Item2' }, { label: 'Item3', type: 'radio', checked: true }, { label: 'Item4', type: 'radio' } ]) // 右下角 icon 被 hover 时的文字 tray.setToolTip('This is my application.') // 设定定应用程式右下角选单 tray.setContextMenu(contextMenu)})
tray.destroy()
:销毁图示选单tray.setToolTip(toolTip)
:设定图示选单被 hover 时的样式tray.displayBalloon(options)
:设显示一个通知(Windows)icon
:图示路径iconType
:none
、info
、warning
、error
或 custom
,预设为 custom
title
:标题(必填)content
:内容(必填)largeIcon
:是否启用大图示(Boolean),预设为 true
noSound
:是否播放音效(Boolean),预设为 false
respectQuietTime
:勿扰模式不显示通知(Boolean),预设为 false
tray.removeBalloon()
:移除通知(Windows)建立选单 template
可以参考官方文件
Notification
Notification 用来建立一个系统通知,使用 new Notification(options)
建立一个通知实例,须于初始化后调用
options
// main.jsconst myNotification = new Notification({ title: '标题', subtitle: '副标题', body: '内容', silent: true, icon: './images/icon.png', timeoutType: 'default'})
title
:标题(必填)body
:内容(必填)subtitle
:副标题(macOS)silent
:是否发出音效(Boolean)icon
:图示路径timeoutType
:通知消失时间,值为 default
或 never
event
// main.jsapp.whenReady().then(() => { const myNotification = new Notification() myNotification.on('show', (e) => { // do something... })})
show
:通知显示时触发click
:通知被点击时触发close
:通知关闭时触发method
// main.jsapp.whenReady().then(() => { const myNotification = new Notification({ title: '标题', body: '内容' }) myNotification.show()})
Notification.show()
:显示通知Notification.close()
:关闭通知通知这边因为各系统都有很多毛,所以如果没有显示请参考官方文件
globalShortcut
globalShortcut 用来自定义快捷键,须于初始化后调用
method
// main.jsconst { app, globalShortcut } = require('electron')app.whenReady().then(() => { // 注册快捷键 CommandOrControl + 0 const ret = globalShortcut.register('CommandOrControl+0', () => { // do something... }) // 返回 Boolean,用于检查快捷键是否注册成功 globalShortcut.isRegistered('CommandOrControl+0')})app.on('will-quit', () => { // 取消注册的快捷键 CommandOrControl + 0 globalShortcut.unregister('CommandOrControl+0') // 取消所有注册的快捷键 globalShortcut.unregisterAll()})
globalShortcut.register(accelerator, callback)
:注册快捷键globalShortcut.unregister(accelerator)
:注消快捷键globalShortcut.registerAll(accelerator, callback)
:一次注册多个快捷键,accelerator
为阵列globalShortcut.unregisterAll()
:注消所有快捷键可定义的 accelerator
请参考官方文件
dialog
dialog 为弹出视窗,用来开启档案选择视窗或讯息弹出视窗等等
method - 档案类型
// main.jsconst { dialog } = require('electron')dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })
dialog.showOpenDialogSync(options)
:打开档案的弹窗,等待选取档案并返回dialog.showOpenDialog(options)
:打开档案的弹窗(返回一个 Promise
)dialog.showSaveDialogSync(options)
:储存档案的弹窗,等待选取档案并返回dialog.showSaveDialog(options)
:储存档案的弹窗(返回一个 Promise
)options - 档案类型
title
:标题defaultPath
:预设位置buttonLabel
:确定按钮的文字filters
:可限制档案类型{ filters: [ { name: 'Images', extensions: ['jpg', 'png', 'gif'] }, { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] }, { name: 'Custom File Type', extensions: ['as'] }, { name: 'All Files', extensions: ['*'] } ]}
properties
:其他功能,阵列里面放以下字串openFile
:可选择文件openDirectory
:可选择资料夹multiSelections
:可选择多个method - 对话框类型
// main.jsconst { dialog } = require('electron')dialog.showMessageBox({ type: 'info', title: '标题', message: '内容' })
dialog.showMessageBoxSync(options)
:讯息的弹窗,等待点选并返回dialog.showMessageBox(options)
:讯息的弹窗(返回一个 Promise
)dialog.showErrorBox(title, content)
:错误视窗options - 对话框类型
type
:类型,none
、info
、error
、question
与 warning
buttons
:按钮文字,一个里面为字串的阵列,选择后回传索引defaultId
:预设选择的按钮索引title
:讯息标题message
:讯息内容detail
:讯息详细文字checkboxLabel
:checkbox 的文字checkboxChecked
:checkbox 预设值icon
:显示的图示cancelId
:取消按钮的索引数,Esc 时返回此索引优化小技巧
我们如果设定视窗 alwaysOnTop
时会发现,视窗将 dialog
盖住了,这时候可以用以下方法
// main.jsimport { BrowserWindow, dialog } from 'electron'// 创建另外一个 alwaysOnTop 的视窗,且不显示于画面const win = new BrowserWindow({ show: false, alwaysOnTop: true })// 在该视窗显示 dialog,并在回传后将视窗销毁dialog.showMessageBox(win, { type: 'info', title: '标题', message: '内容' }).then(() => { win.destroy()})
主进程与渲染进程 API
这边介绍的 API 在主进程能用,在渲染进程也可以使用,可以将值写入全域,以便在 renderer.js
使用
// preload.jsconst { clipboard, shell } = require('electron')window.clipboard = clipboardwindow.shell = shell
clipboard
clipboard 就是剪贴簿的功能,可记录文字、HTML、图片等等
method
// main.jsconst { clipboard } = require('electron')clipboard.availableFormats([ 'text/plain', 'text/html' ])clipboard.writeText('範例字串', 'selection')console.log(clipboard.readText('selection'))
clipboard.writeText(text)
:将文字写入剪贴簿clipboard.readText()
:读取剪贴簿的文字clipboard.writeHTML(markup)
:将 html 写入剪贴簿clipboard.readHTML()
:读取剪贴簿的 htmlclipboard.writeImage(image)
:将图片写入剪贴簿clipboard.readImage()
:读取剪贴簿的图片clipboard.writeRTF(text)
:将 RTF 写入剪贴簿clipboard.readRTF()
:读取剪贴簿的 RTFclipboard.availableFormats([type])
:定义剪贴簿可用格式clipboard.clear()
:清除剪贴簿内容clipboard.write(data)
:可一次写入多笔资讯text
:文字html
:htmlimage
:图片rtf
:RTFclipboard.write({ text: 'test', html: '<b>Hi</b>', rtf: '{\\rtf1\\utf8 text}',})
shell
shell 可以使用预设的应用程式开启档案,常用在用浏览器开启档案
method
// main.jsconst { shell } = require('electron')shell.openExternal('https://github.com')
shell.showItemInFolder(fullPath)
:打开该文件所在目录并选取该文件shell.openPath(path)
:使用预设方式打开该文件shell.openExternal(url)
:使用预设浏览器打开该网址shell.moveItemToTrash(fullPath)
:删除该档案shell.beep()
:播放提示音nativeImage
nativeImage 是一个包装图片的物件,Electron 内许多回传图片都是此类型
// main.jsconst { BrowserWindow, Tray, clipboard } = require('electron')// 以下返回的皆为 nativeImage 物件const appIcon = new Tray('/Users/somebody/images/icon.png')const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })const image = clipboard.readImage()
method - 直接调用
nativeImage.createFromPath(path)
:依路径建立一个 nativeImage
物件nativeImage.createFromBitmap(buffer, options)
:依档案建立一个 nativeImage
物件nativeImage.createFromBuffer(buffer, options)
:依档案建立一个 nativeImage
物件nativeImage.createFromDataURL(dataURL)
:依 dataURL 建立一个 nativeImage
物件nativeImage.createFromPath(path)
:依路径建立一个 nativeImage
物件method - 操作实例
image.toPNG(path)
:返回 Bufferimage.toJPEG(quality)
:返回 Buffer,quality 为 0 ~ 100image.toBitmap(path)
:返回 Bufferimage.toDataURL(path)
:返回 Stringimage.getBitmap(path)
:返回 Buffer渲染进程 API
这边介绍的 API 仅在渲染进程能用,无法在主进程使用
remote
remote 是很特别的方法,他的作用是为了让渲染进程使用部分主进程的功能,使用方法如下
// main.jsconst { BrowserWindow } = require('electron')const path = require('path')const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), enableRemoteModule: true // 启用 remote 模块 }})win.loadURL('https://github.com')
// preload.jsconst { dialog } = require('electron').remotewindow.dialog = dialog
// renderer.jswindow.dialog.showErrorBox('标题', '内容')
method
remote.require(module)
:载入相对路径模块remote.getCurrentWindow()
:回传当前视窗实例emote.getCurrentWebContents()
:回传当前视窗内容实例// preload.jsconst foo = require('electron').remote.require('./foo')require('electron').remote.getCurrentWindow().on('close', () => { // do something...})
结语
读文件真的太苦了