Vue3和Electron实现桌面端应用详解(2)

我们看到新加了很多的依赖库,还添加了一个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); }); });

主线程收到内容然后存入文件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfjdf.html