關(guān)于Electron
Electron是由Github開(kāi)發(fā),用HTML,CSS和JavaScript來(lái)構(gòu)建跨平臺(tái)桌面應(yīng)用程序的一個(gè)開(kāi)源庫(kù)。
Electron通過(guò)將Chromium和Node.js合并到同一個(gè)運(yùn)行時(shí)環(huán)境中,并將其打包為Mac,Windows和Linux系統(tǒng)下的應(yīng)用來(lái)實(shí)現(xiàn)這一目的。
按我的理解,就是用讓你用 JavaScript 代碼去操作系統(tǒng)的API,達(dá)到與原生應(yīng)用相似的體驗(yàn),當(dāng)然GUI則是一個(gè)web界面,簡(jiǎn)而言之就是個(gè)chrome內(nèi)核的瀏覽器。
Electron用法
Electron Application使用 JavaScript 開(kāi)發(fā),工作原理與方法與 node.js 相同,引入 electron 模塊,包含了 Electron 提供的所有API和功能。
項(xiàng)目需求
為我們web端服務(wù)做的前期demo,功能上很簡(jiǎn)單,APP顯示我們的web站點(diǎn),當(dāng)即時(shí)通訊有消息送達(dá)時(shí),系統(tǒng)托盤(pán)需要閃爍,右鍵點(diǎn)擊系統(tǒng)托盤(pán)需要有如下功能
功能實(shí)現(xiàn)
app顯示web站點(diǎn)
引入 electron 模塊,使用 BrowserWindow 類渲染窗口。
const { app, BrowserWindow } = require('electron')
//創(chuàng)建主頁(yè)面
function createWindow() {
mainWindow = new BrowserWindow({
show: false,
autoHideMenuBar: true,
title: 'ElectronApp'
})
//最大化
mainWindow.maximize();
// 然后加載應(yīng)用的 index.html。
mainWindow.loadFile('./app/index.html');
//窗口關(guān)閉時(shí)觸發(fā)
mainWindow.on('closed', () => {
mainWindow = null
});
//打開(kāi)開(kāi)發(fā)者工具
mainWindow.webContents.openDevTools();
//渲染完成后
mainWindow.on('ready-to-show', function () {
//顯示窗口
mainWindow.show();
//頁(yè)面聚焦
mainWindow.focus();
});
}
這里加載html方法有兩種:
1.使用 loadURL('https://electronjs.org') 直接指向某個(gè)地址。
2.使用 loadFile('./app/index.html') 指向html文件,在index頁(yè)面中,使用 <webview> 標(biāo)簽加載 url 地址。
在實(shí)際使用中,第一種適配我們項(xiàng)目時(shí)有bug,推薦使用第二種加載方式。
系統(tǒng)配置
在 electron 模塊中引入,globalShortcut(全局快捷鍵),Menu(菜單),Tray(托盤(pán)),ipcMain(異步通信),shell(系統(tǒng)命令)。
const {app, BrowserWindow, globalShortcut, Menu, Tray, ipcMain, shell} = require('electron')
let tray
//托盤(pán)右鍵菜單
let template = [
{
label: '訪問(wèn)地址、快捷鍵、開(kāi)機(jī)啟動(dòng)設(shè)置', click: function () {
createConfig();
}
},
{
label: '打開(kāi)主界面', click: function () {
mainWindow.show();
}
},
{
label: '即時(shí)通訊'
},
{
label: '使用系統(tǒng)瀏覽器打開(kāi)web站點(diǎn)', click: function () {
shell.openExternal(configuration.readSettings('global_url'));
}
},
{
label: "退出", role: 'quit'
}
];
app.on('ready', () => {
//創(chuàng)建窗口
createWindow();
//系統(tǒng)托盤(pán)
tray = new Tray('./app/img/app-icon.ico');
//設(shè)置此托盤(pán)圖標(biāo)的懸停提示內(nèi)容
tray.setToolTip('中科天翔');
const contextMenu = Menu.buildFromTemplate(template);
tray.setContextMenu(contextMenu);
tray.on("click", function () {
//閃爍時(shí)點(diǎn)擊彈出即時(shí)通訊頁(yè)面
if (flashTrayTimer) {
mainWindow.show();
//顯示即時(shí)通訊
mainWindow.webContents.send('ping', 'openMessage');
//停止閃爍
flashTray(false);
tray.setImage('./app/img/app-icon.ico')
} else {
//主窗口顯示隱藏切換
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
}
})
//設(shè)置默認(rèn)配置參數(shù)
setBootStart();
//設(shè)置全局快捷鍵
setGlobalShortcuts();
})
即時(shí)通訊閃爍圖標(biāo)
整體思路大概是這樣的,通過(guò)事件監(jiān)聽(tīng)cookie變化,web端即時(shí)通訊收到消息以后,將 cookie 值變?yōu)?new ,觸發(fā)異步通信 ipcRenderer 發(fā)送消息,ipcMain 監(jiān)聽(tīng)消息 ,觸發(fā)函數(shù)開(kāi)始閃爍圖標(biāo)(就是將圖標(biāo)與空白圖標(biāo)來(lái)回切換),當(dāng)然打開(kāi)托盤(pán)即時(shí)通訊也有類似操作。
//收到消息
webview.addEventListener('dom-ready', () => {
var currCookies = webview.getWebContents().session.cookies;
webview.getWebContents().openDevTools();
//監(jiān)聽(tīng)cookie
currCookies.addListener('changed', (event, cookie, cause, removed) => {
//客戶端打開(kāi)即時(shí)通訊
if (cookie.name == 'electron' && cookie.value == 'open') {
ipcRenderer.send('open-message');
}
//有新消息提醒閃爍
if (cookie.name == 'electron' && cookie.value == 'new') {
ipcRenderer.send('receive-message');
}
});
})
//即時(shí)通訊
ipcMain.on('receive-message', function () {
//先關(guān)閉再閃爍
flashTray(false);
tray.setImage('./app/img/app-icon.ico');
flashTray(true);
});
ipcMain.on('open-message', function () {
//關(guān)閉托盤(pán)閃爍
flashTray(false);
tray.setImage('./app/img/app-icon.ico');
});
修改配置
修改配置思路比較簡(jiǎn)單,通過(guò) nconf 模塊,將配置保存在本地,app初始化的時(shí)候讀取配置。
喚醒/隱藏界面快捷鍵
在配置界面的html中,將喚醒/隱藏界面的 input 標(biāo)簽加上 onkeydown 事件,來(lái)監(jiān)聽(tīng)用戶鍵盤(pán)按鍵操作,保存時(shí)寫(xiě)入配置文件。