原因
有个demo需要在electron写好的渲染进程之前加一个登录界面,想来想去,直接在开始前再加一个登录窗口;
一切从简,尽量简单,不想多费一点脑子
整体思路
markdown
应用启动时,先创建 ***登录窗口*** ,加载登录页面(HTML)。
用户输入账号密码后,通过渲染进程与主进程通信,验证账号密码。
验证成功后,关闭登录窗口,打开主页面窗口;验证失败则提示错误。
登录界面如下:
html
<!-- login.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
<style>
/* 简单样式,可自定义 */
.login-container {
width: 300px;
margin: 100px auto;
text-align: center;
}
input {
width: 100%;
margin: 10px 0;
padding: 8px;
}
button {
padding: 8px 20px;
background: #0078d7;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<div class="login-container">
<h2>请登录</h2>
<input type="text" id="username" placeholder="账号" />
<input type="password" id="password" placeholder="密码" />
<button onclick="login()">登录</button>
<p id="error" style="color: red;"></p>
</div>
<script>
// 引入Electron的渲染进程API
const { ipcRenderer } = require('electron');
// 登录逻辑
function login() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
// 发送账号密码到主进程验证
ipcRenderer.send('login-request', { username, password });
}
// 接收主进程的验证结果
ipcRenderer.on('login-result', (event, { success, message }) => {
if (success) {
// 验证成功,通知主进程打开主页面
ipcRenderer.send('open-main-window');
} else {
// 显示错误信息
document.getElementById('error').textContent = message;
}
});
</script>
</body>
</html>
修改主进程代码(控制窗口逻辑)
js
// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
// 声明窗口变量
let loginWindow = null;
let mainWindow = null;
// 创建登录窗口
function createLoginWindow() {
loginWindow = new BrowserWindow({
width: 400,
height: 300,
resizable: false,
// 禁止调整大小
webPreferences: {
nodeIntegration: true,
// 允许渲染进程使用Node API(Electron 12+需配合contextIsolation: false)
contextIsolation: false,
enableRemoteModule: false
}
});
// 加载登录页面
loginWindow.loadFile('login.html');
// 窗口关闭时清空变量
loginWindow.on('closed', () => { loginWindow = null; }); }
// 创建主页面窗口
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// 加载已有渲染页面(替换为主页面路径)
mainWindow.loadFile('main-page.html'); // 例如:'index.html'
mainWindow.on('closed', () => { mainWindow = null; });
}
// 监听应用启动
app.on('ready', createLoginWindow);
// 监听所有窗口关闭
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
// macOS下窗口关闭不退出应用
app.quit();
}
});
app.on('activate', () => {
if (loginWindow === null && mainWindow === null) {
createLoginWindow();
}
});
// 主进程处理登录请求(核心:验证账号密码)
ipcMain.on('login-request', (event, { username, password }) => {
// 这里写验证逻辑(示例:固定账号密码,实际项目需对接后端API或数据库)
const validUsername = 'admin';
const validPassword = '123456';
if (username === validUsername && password === validPassword) {
// 验证成功,返回结果给渲染进程
event.reply('login-result', { success: true });
} else {
// 验证失败
event.reply('login-result', { success: false, message: '账号或密码错误' });
}
});
// 监听打开主窗口的请求
ipcMain.on('open-main-window', () => {
if (loginWindow) {
loginWindow.close(); // 关闭登录窗口
}
createMainWindow(); // 打开主窗口
});
项目结构:
js
your-electron-app/
├── public/ # 静态资源目录(存放HTML、CSS、JS等)
│ ├── index.html # 你的主页面(原渲染页面)
│ └── login.html # 登录页面(建议放在这里)
├── src/
│ ├── main/
│ │ └── main.js # 主进程代码
│ └── renderer/ # 渲染进程代码(如果有的话)
├── package.json
└── ...
写在最后
有个坑,我的打包命令是:
json
"build":{
"files":[
"dist",
"node_modules",
"packages.json"
]
}
最后没login.html没加到dist/app/路径下,直接给放进去就行。