简介
Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。
思路:监听键盘keyDownEvent > 功能函数funObj > 快捷键映射功能函数keyList > 当前快捷键匹配功能函数keyMap > 执行doFun
窗口通信:主传electron > electron传子,反之,子传electron > electron传主
- 渲染文件vue
(1)监听keydown或keyup
window.addEventListener("keydown", doKeyDownEvent, false);
const doKeyDownEvent = (e: KeyboardEvent) => {
// 快捷键功能映射对象
const funObj = [
{
name: "backToHome",
fun: backToHome,
},
{
name: "saveData",
fun: updateWorkData,
},
//
];
keyDownEvent(e, store, mainSceneObj, funObj);
};
const doKeyUpEvent = (e: KeyboardEvent) => {
keyUpEvent(e, store, mainSceneObj);
};
(2)功能键-功能函数-键盘key
//功能键-功能函数名映射
const keyList = [
{
alias: "显示或隐藏辅助页",
name: "assistDisplayMode",
key: "ctrl+F5",
},
//...
];
export const keyMap = (event: KeyboardEvent, keyList: any) => {
//处理一些组合键
let auxKey: string = '';
if (!event.shiftKey && !event.ctrlKey && event.altKey) {
auxKey = "alt";
} else if (!event.shiftKey && event.ctrlKey && !event.altKey) {
auxKey = "ctrl";
} else if (event.shiftKey && !event.ctrlKey && !event.altKey) {
auxKey = "shift";
} else if (!event.shiftKey && event.ctrlKey && event.altKey) {
auxKey = "alt+ctrl";
} else if (event.shiftKey && !event.ctrlKey && event.altKey) {
auxKey = "alt+shift";
} else if (event.shiftKey && event.ctrlKey && !event.altKey) {
auxKey = "ctrl+shift";
} else if (event.shiftKey && event.ctrlKey && event.altKey) {
auxKey = "alt+ctrl+shift";
} else {
auxKey = "";
};
const keyValue: string = auxKey ? auxKey + '+' + event.key : event.key;
const keyInfo: any = keyList.find((k: any) => k.key === keyValue);
return keyInfo ? keyInfo.name : null;
}
export const keyDownEvent = (event: KeyboardEvent, store: any, mainSceneObj: any, funObj: any = null) => {
event.preventDefault();
const keyName = keyMap(event, keyList);
// console.log("keydown", keyName)
//Esc - 撤销编辑
if (keyName == "cancel") {
doFun(funObj, keyName);
}
//打开辅助页
else if (keyName == "assistDisplayMode") {
const arr = {}//传给childwin的数据
// 调用electron声明方法
window.api.send("m2e_send", { method: "createChildWindow", obj: arr });
}
}
const doFun = (funObj: any, keyName: string, params: any = null) => {
funObj.forEach(f => {
if (f.name == keyName) {
if (params) {
f.fun(params);
} else {
f.fun()
}
}
});
}
- electron文件
包含窗口定义,通信事件
(1)入口文件
//main.ts
const { app, BrowserWindow, ipcMain, dialog } = require("electron");
let mainWin;
let childWin;
const NODE_ENV = process.env.NODE_ENV;
/* 打开主窗体 */
const createMainWindow = () => {
// BrowserWindow初始化窗口信息
mainWin = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
//@ts-ignore
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegrationInWorker: true,
webSecurity: false,
preload: path.join(__dirname, "preload.ts"),
},
title: "主窗口",
show: false,
})
mainWin.loadURL(
NODE_ENV === 'development' ? 'http://localhost:5173/' : `file://${path.join(__dirname, '../dist/index.html')}`
)
if (NODE_ENV === 'development') {
mainWin.webContents.openDevTools()//调试工具
}
mainWin.once("ready-to-show", () => {
mainWin.show();
mainWin.maximize();
});
}
const createChildWindow = () => {
// BrowserWindow初始化窗口信息,同createMainWindow
};
// electron初始化之后默认打开主窗口
app.whenReady().then(() => {
mainWin = null;
childWin = null;
createMainWindow();
});
//m2e_send:主窗口给子窗口
ipcMain.on("m2e_send", mainWinToElectron);
//mainWin -> electron
function mainWinToElectron (e, res) {
// console.log("mainWIn", res)
if (res.method == "changeChildWinState") changeChildWinState()
}
/* 打开辅助窗体 */
function changeChildWinState (e, res) {
if (childWin != null) {
childWin.close();
} else {
createChildWindow()
}
}
(2)渲染器
contextBridge将electron定义的事件抛出,使得渲染文件vue可以通过window.api.send("m2e_send", { method: "createChildWindow", obj: arr });
调用
//preload.ts
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["m2e_send"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
});