我们看到新加了很多的依赖库,还添加了一个background.ts文件。简单介绍下,这个文件执行在主线程,其他的页面都是在渲染线程。渲染线程有很多限制的,有些功能只能在主线程执行,这里就不具体展开了。
执行npm run electron:serve看效果
至此,就可以看到桌面应用的效果了,并且边修改Vue的代码,桌面应用也能实时看到修改后的效果。
优化功能 启动全屏显示引入screen
import { screen } from "electron";
创建窗口的时候设置为screen大小
<!-- background.ts --> async function createWindow() { const { width, height } = screen.getPrimaryDisplay().workAreaSize; const win = new BrowserWindow({ width, height, // 省略... }); // 省略... }
这样应用启动的时候就是全屏显示了。
修改菜单栏定义菜单栏
<!-- background.ts --> const template: Array<MenuItemConstructorOptions> = [ { label: "MarkDown", submenu: [ { label: "关于", accelerator: "CmdOrCtrl+W", role: "about", }, { label: "退出程序", accelerator: "CmdOrCtrl+Q", role: "quit", }, ], }, { label: "文件", submenu: [ { label: "打开文件", accelerator: "CmdOrCtrl+O", click: ( item: MenuItem, focusedWindow: BrowserWindow | undefined, _event: KeyboardEvent ) => { // TODO: 打开文件 }, }, { label: "存储", accelerator: "CmdOrCtrl+S", click: ( item: MenuItem, focusedWindow: BrowserWindow | undefined, _event: KeyboardEvent ) => { // TODO: 存储内容 }, }, ], }, { label: "编辑", submenu: [ { label: "撤销", accelerator: "CmdOrCtrl+Z", role: "undo", }, { label: "重做", accelerator: "Shift+CmdOrCtrl+Z", role: "redo", }, { type: "separator", }, { label: "剪切", accelerator: "CmdOrCtrl+X", role: "cut", }, { label: "复制", accelerator: "CmdOrCtrl+C", role: "copy", }, { label: "粘贴", accelerator: "CmdOrCtrl+V", role: "paste", }, ], }, { label: "窗口", role: "window", submenu: [ { label: "最小化", accelerator: "CmdOrCtrl+M", role: "minimize", }, { label: "最大化", accelerator: "CmdOrCtrl+M", click: ( item: MenuItem, focusedWindow: BrowserWindow | undefined, _event: KeyboardEvent ) => { if (focusedWindow) { focusedWindow.maximize(); } }, }, { type: "separator", }, { label: "切换全屏", accelerator: (function () { if (process.platform === "darwin") { return "Ctrl+Command+F"; } else { return "F11"; } })(), click: ( item: MenuItem, focusedWindow: BrowserWindow | undefined, // eslint-disable-next-line @typescript-eslint/no-unused-vars _event: KeyboardEvent ) => { if (focusedWindow) { focusedWindow.setFullScreen(!focusedWindow.isFullScreen()); } }, }, ], }, { label: "帮助", role: "help", submenu: [ { label: "学习更多", click: function () { shell.openExternal("http://electron.atom.io"); }, }, ], }, ];
具体如何定义参阅Electron Menu。
打开文件和存储目前还没实现,后面实现。
设置菜单栏
import { Menu } from "electron"; app.on("ready", async () => { // 省略... // 创建菜单 Menu.setApplicationMenu(Menu.buildFromTemplate(template)); });
在ready钩子函数中进行设置Menu。
效果
编辑器打开markdonw文件的内容主线程选择文件,将文件路径传给渲染线程
<!-- background.ts --> dialog .showOpenDialog({ properties: ["openFile"], filters: [{ name: "Custom File Type", extensions: ["md"] }], }) .then((res) => { if (res && res["filePaths"].length > 0) { const filePath = res["filePaths"][0]; // 将文件传给渲染线程 if (focusedWindow) { focusedWindow.webContents.send("open-file-path", filePath); } } }) .catch((err) => { console.log(err); });
showOpenDialog是打开文件的方法,我们这里指定了只打开md文件;
获得文件路径后,通过focusedWindow.webContents.send("open-file-path", filePath);这个方法将文件路径传给渲染线程。
渲染线程取到文件路径,读取文件内容,赋值给markdown编辑器
<!-- App.vue --> import { ipcRenderer } from "electron"; import { readFileSync } from "fs"; export default defineComponent({ // 省略... setup() { const content = ref(""); onMounted(() => { // 1. ipcRenderer.on("open-file-path", (e, filePath: string) => { if (filePath && filePath.length > 0) { // 2. content.value = readFileSync(filePath).toString(); } }); }); return { content }; }, });
vue添加node支持
<!-- vue.config.js --> module.exports = { pluginOptions: { electronBuilder: { nodeIntegration: true, }, }, };
效果
markdonw的内容存入文件主线程发起向渲染线程获取编辑器内容的请求
<!-- background.js --> if (focusedWindow) { focusedWindow.webContents.send("get-content", ""); }
渲染线程主线程向返回编辑器的内容
<!-- App.vue --> onMounted(() => { ipcRenderer.on("get-content", () => { ipcRenderer.send("save-content", content.value); }); });
主线程收到内容然后存入文件