在Electron中我们创建一个托盘需要如下几个文件:
1. main.js 用来存放应用代码。
2. 一张PNG格式的图片用作应用图标。
3. 一个package.json文件用来描述应用配置。
下面是我们项目的目录架构如下:
|--- electron-demo5 | |--- node_modules | |--- app.css | |--- app.js | |--- main.js | |--- icon@2x.png | |--- index.html | |--- package.json
index.html 是用来展示笔记的内容,如下html代码:
<html> <head> <title>tray-app-electron</title> <link href="./app.css" rel="stylesheet" /> </head> <body> <h1 id="app"></h1> <div id="contents"></div> <script type="text/javascript" src="./app.js"></script> </body> </html>
package.json 代码如下:
{ "name": "tray-app-electron", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { }, "author": "kongzhi", "license": "ISC", "dependencies": { "electron": "^6.0.0" } }
main.js 代码如下:
'use strict'; const { app, Menu, Tray, BrowserWindow } = require('electron') let appIcon = null; let mainWindow = null; const notes = [ { title: 'todo list', contents: '111111' }, { title: 'xxxxx', contents: '2222' } ]; function displayNote (note) { // 使用 webContents API 向浏览器窗口发送数据来显示笔记内容 mainWindow.webContents.send('displayNote', note); } function addNoteToMenu (note) { return { label: note.title, type: 'normal', click: () => { displayNote(note); } } } app.on('ready', () => { // 创建一个带图标的托盘应用 appIcon = new Tray('icon@2x.png'); // 为托盘应用创建上下文菜单,对笔记进行迭代并添加为菜单项 let contextMenu = Menu.buildFromTemplate(notes.map(addNoteToMenu)); appIcon.setToolTip('Notes app'); // 将上下文菜单绑定到托盘应用上 appIcon.setContextMenu(contextMenu); mainWindow = new BrowserWindow({ 800, height: 600, webPreferences: { nodeIntegration: true } }); // 添加如下代码 可以调试 mainWindow.webContents.openDevTools(); mainWindow.loadURL(`file://${__dirname}/index.html`); // 当应用视窗加载好后,默认显示第一个笔记内容 mainWindow.webContents.on('dom-ready', () => { displayNote(notes[0]); }); });
如上代码就创建了一个托盘应用,以及它的菜单, 同时BrowserWindow负责显示笔记内容,当我们的菜单笔记项被单击的时候,就会调用我们的 app.js 代码如下的函数:
function displayNote(event, note) { document.getElementById("app").innerText = note.title; document.getElementById("contents").innerText = note.contents; } // Electron 的 ipcRenderer模块监听由后端进程触发的事件 const ipc = require('electron').ipcRenderer; /* 菜单项被单击或当应用加载的时候,ipcRenderer模块会接收到事件以及note对象并将其 传递给 displayNote 函数 */ ipc.on('displayNote', displayNote);
如上代码,会使用 electron中的ipcRenderer模块来接收displayNote事件以及由main进程传递给renderer进程的note对象。这样我们就可以在 BrowserWindow 进程中更新HTML内容了。
electron的ipcRenderer模块可以发送以及接收来自或传递给Electron main 进程的数据,在托盘应用上下文中,后端进程通过 web contents API将数据传递给浏览器视窗,因此, displayNote事件以及note对象由后端传递给前端,ipcRenderer则监听该事件。当事件触发的时候,ipcRenderer会获取到note对象并将其传递给负责将笔记内容插入到html的函数。
当我们运行 electron . 的时候,我们会在我们的mac系统顶部有一个图标,如下所示:
同时也会打开一个托盘这样的,如下图所示:
当我们点击图标的时候,它会有一个列表,如下图所示:
当我们点击 xxx 列表项的时候,托盘内容就会显示 xxxx 对应的内容了,如下图所示:
当我们切换到 todo list 列表的时候,就会显示 todo list 对应的内容了,如下图所示:
更多的系统托盘知识,请看官网API (https://electronjs.org/docs/api/tray)