在 Electron 應用程式中,呼叫 window.prompt()、window.alert() 或 window.confirm() 等原生瀏覽器對話框時,會發現這些函式完全無效,沒有任何對話框彈出。這是 Electron 的架構設計造成的,需要用其他方式替代。
為什麼 Electron 不支援原生 Dialog?
Electron 採用 Main Process / Renderer Process 的雙進程架構:
- Main Process(主進程):Node.js 環境,負責管理視窗、系統資源等,對應
main.js
- Renderer Process(渲染進程):Chromium 環境,負責顯示 UI,對應網頁內容
window.prompt() 等原生對話框在標準瀏覽器中是同步阻塞的,但 Electron 基於安全性和效能考量,在 Renderer Process 中停用了這些同步對話框。呼叫後會被靜默忽略,prompt() 永遠回傳 null。
替代方案一:Electron 內建 dialog 模組(Main Process)
Electron 提供 dialog 模組,可在 Main Process 中顯示系統原生對話框:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// main.js(Main Process)
const { app, BrowserWindow, dialog, ipcMain } = require('electron');
// 監聽來自 Renderer 的請求
ipcMain.handle('show-input-dialog', async (event, message) => {
const result = await dialog.showMessageBox({
type: 'question',
buttons: ['確定', '取消'],
title: '輸入',
message: message,
});
return result.response; // 0 = 確定, 1 = 取消
});
|
1
2
3
4
5
6
7
|
// renderer.js(Renderer Process)
const { ipcRenderer } = require('electron');
async function myPrompt(message) {
const response = await ipcRenderer.invoke('show-input-dialog', message);
return response === 0; // 回傳 true 代表點了確定
}
|
注意:dialog 模組只能在 Main Process 使用,必須透過 IPC(Inter-Process Communication)從 Renderer 呼叫。
替代方案二:自訂 HTML Modal 對話框
直接在頁面中用 HTML + CSS 實作對話框,是最靈活的方式:
1
2
3
4
5
6
7
8
9
10
|
<!-- 對話框 HTML -->
<div id="custom-prompt" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999;">
<div style="background:white; margin:100px auto; padding:20px; width:300px; border-radius:8px;">
<p id="prompt-message"></p>
<input type="text" id="prompt-input" style="width:100%; padding:8px;">
<br><br>
<button onclick="promptConfirm()">確定</button>
<button onclick="promptCancel()">取消</button>
</div>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
function showPrompt(message) {
return new Promise((resolve) => {
document.getElementById('prompt-message').textContent = message;
document.getElementById('prompt-input').value = '';
document.getElementById('custom-prompt').style.display = 'block';
window.promptConfirm = () => {
const value = document.getElementById('prompt-input').value;
document.getElementById('custom-prompt').style.display = 'none';
resolve(value);
};
window.promptCancel = () => {
document.getElementById('custom-prompt').style.display = 'none';
resolve(null);
};
});
}
// 使用方式
const name = await showPrompt('請輸入您的姓名:');
|
替代方案三:使用第三方套件
electron-prompt
專為 Electron 設計的 prompt 替代套件:
1
|
npm install electron-prompt
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
const prompt = require('electron-prompt');
prompt({
title: '輸入',
label: '請輸入您的姓名:',
value: '預設值',
inputAttrs: {
type: 'text'
},
type: 'input'
}).then((result) => {
if (result === null) {
console.log('使用者取消');
} else {
console.log('輸入值:', result);
}
});
|
SweetAlert2
功能豐富的 dialog 替代套件,支援各種樣式:
1
|
npm install sweetalert2
|
1
2
3
4
5
6
7
8
9
10
|
const Swal = require('sweetalert2');
const { value } = await Swal.fire({
title: '請輸入您的姓名',
input: 'text',
inputPlaceholder: '輸入姓名...',
showCancelButton: true,
});
console.log('輸入值:', value);
|
方案比較
| 方案 |
適用情境 |
優點 |
缺點 |
| Electron dialog(IPC) |
需要系統原生外觀 |
與 OS 整合,使用者熟悉 |
需要 IPC,程式碼較複雜 |
| 自訂 HTML Modal |
需要高度自訂樣式 |
完全控制外觀 |
需要自行實作 |
| electron-prompt |
快速替換 prompt() |
簡單易用 |
功能較簡單 |
| SweetAlert2 |
需要豐富的 UI |
外觀漂亮、功能多 |
需要引入額外套件 |
參考資料