這次來說明一下 Electron 的 IPC 機制
Electron 使用 Chromium multi-process 的機制,由 main process 來創建 application
renderer process 來負責繪製 web page,而 process 之間是無法直接溝通的
那如果想要 web page 和 GUI 有互動,例如可以透過 button 來關閉整個視窗,那該怎麼做?
這個程式會示範如何透過 IPC,讓使用者可以透過在 web page 的 button來關閉整個應用程式
- 先說明一下這次的資料結構
ipc
|- app
| |- index.html
| |- index.js
|
|- main.js
|- package.json
- index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Electron IPC</title> | |
</head> | |
<body> | |
<center> | |
<h1>Electron IPC</h1> | |
<button id="close">Close Window</button> | |
<script src="index.js"></script> | |
</center> | |
</body> | |
</html> |
- index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
//> ipc for renderer process | |
let ipcRenderer = require('electron').ipcRenderer; | |
//> close button | |
let closeBtn = document.querySelector('#close'); | |
closeBtn.addEventListener('click', () => { | |
//> send a message to close-main-window channel without args | |
ipcRenderer.send('close-main-window'); | |
}); |
之後就可以透過這個 instance 來和 main process 做溝通
這邊要注意一點是,在 renderer process 就只能拿 ipcRenderer
如果改寫成
let ipcRenderer = require('electron').ipcMain
會發現 ipcRenderer 會是 undefined
這是因為 electron 會區別是 main process 還是 renderer process 的關係
接著讓按鈕監聽 click 事件
當按鈕被點擊後,透過 ipcRenderer 送訊息到 close-main-window 這個 channel
來和 main process 溝通
- mina.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const {app, BrowserWindow, ipcMain} = require('electron'); | |
const path = require('path'); | |
const url = require('url'); | |
//> keep a global reference of the window object, if you don't, the window will | |
//> be closed automatically when the JavaScript object is garbage collected. | |
let win = null; | |
//> create the browser window | |
function createWindow() { | |
win = new BrowserWindow({width: 400, height: 300}); | |
//> load the index.html of the app | |
win.loadURL(url.format({ | |
protocol: 'file', | |
slashes: true, | |
pathname: path.join(__dirname, 'app/index.html') | |
})); | |
//> open the DevTools | |
//win.webContents.openDevTools(); | |
//> emitted when the window is closed | |
win.on('closed', () => { | |
//> dereference the window object, usually you would store windows | |
//> in an array if your app supports multi windows, this is the time | |
//> when you should delete the corresponding element | |
win = null | |
}); | |
} | |
//> This method will be called when Electron has finished | |
//> initialization and is ready to create browser windows. | |
//> Some APIs can only be used after this event occurs. | |
app.on('ready', createWindow); | |
//> Quit when all windows are closed | |
app.on('window-all-closed', () => { | |
//> On macOS it is common for applications and their menu bar | |
//> to stay active until the user quits explicitly with Cmd+Q | |
if(process.platform !== 'darwin') { | |
app.quit(); | |
} | |
}); | |
app.on('activate', () => { | |
//> On macOS it is common to re-create a window in the app when the | |
//> dock icon is clicked and there are no other windows open | |
if(win === null) { | |
createWindow(); | |
} | |
}); | |
//> ipcMain is ipc of main process | |
//> ipcMain listen to close-main-window channel here | |
ipcMain.on('close-main-window', () => { | |
console.log('closed by ipc'); | |
app.quit(); | |
}); |
然後在最後面,叫 ipcMain 監聽 close-main-window 這個 channel
當從這個 channel 收到訊息的時候,就把視窗關掉
- 執行程式
> npm install
> ./node_modules/.bin/electron .


沒有留言:
張貼留言