# Electron桌面应用笔记_结合vue和react **Repository Path**: fxym888/ElectronNotes ## Basic Information - **Project Name**: Electron桌面应用笔记_结合vue和react - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-02-03 - **Last Updated**: 2024-12-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #1. 简介 - [官网](https://www.electronjs.org/) - Electron 是由 GitHub 众多开发者开发的一个开源项目,能够使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序 # 2. 快速上手 ## 2.1 安装 electron 初始化 package.json 文件 - npm init 安装 electron - cnpm i electron –S ## 2.2 配置为入口文件 ```js { "name": "Electron", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "electron": "electron ." // 这里新增 }, "author": "", "license": "ISC", "dependencies": { "electron": "^17.0.0" } } ``` ## 2.3 创建 main.js 文件 ```js const { app } = require("electron"); // { app }用来控制程序的生命周期 // 当 Electron 完成初始化时,触发一次 app.on("ready", () => {}); ``` ## 2.4 创建窗口 ```js const { app, BrowserWindow } = require("electron"); // { app }用来控制程序的生命周期 // { BrowserWindow }用来桌面应用窗口配置 // 当 Electron 完成初始化时,触发一次 app.on("ready", () => { // 设置启动窗口配置 new BrowserWindow({ width: 800, height: 800, }); }); ``` ### 2.5 如何导入内容 ```js app.on("ready", () => { // 用const定义myBrowserWindow窗口实例 const myBrowserWindow = new BrowserWindow({ width: 800, height: 800, }); // 用创建的myBrowserWindow窗口实例上的loadFile方法引入需要展示的内容文件 myBrowserWindow.loadFile("./src/index.html"); }); ``` # 3. 自动刷新页面 - 安装插件 ```js cnpm i -D electron-reloader ``` - 在入口引入插件 ```js const reloader = require("electron-reloader"); reloader(module); ``` # 4. 主进程和渲染进程 Electron 运行 `package.json` 的 `main` 脚本的进程被称为**主进程**。 在主进程中运行的脚本通过创建 web 页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。 ```js const { app, BrowserWindow } = require("electron"); // 主进程打印会在cmd里面显示 console.log(module); ``` 由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它的叫**渲染进程**的进程中。 在普通的浏览器中,web 页面无法访问操作系统的原生资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些底层交互。 ctrl+shift+i 打开渲染进程调试 默认打开调试 ```js app.on("ready", () => { const myBrowserWindow = new BrowserWindow({ width: 800, height: 800, }); // 默认打开渲染进程调试工具 myBrowserWindow.webContents.openDevTools(); myBrowserWindow.loadFile("./src/index.html"); }); ``` # 5. 自定义原生菜单 ![avatar](./readme_img/1.jpg) ## 5.1 自定义菜单 详细文档:https://www.electronjs.org/zh/docs/latest/api/menu ```js const { app, BrowserWindow, Menu } = require("electron"); app.on("ready", () => { const myBrowserWindow = new BrowserWindow({ width: 800, height: 800, }); myBrowserWindow.loadFile("./src/index.html"); // 定义自定义菜单 const template = [ { label: "文件", submenu: [ { label: "新建窗口", }, ], }, { label: "编辑", submenu: [ { label: "新建窗口", }, ], }, ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); }); ``` 效果图 ![avatar](./readme_img/2.jpg) ## 5.2 给菜单定义点击事件 1、点击打开新窗口 ```js submenu: [ { label: "新建窗口", click: () => { const newMainWindow = new BrowserWindow({ width: 300, height: 300, }); newMainWindow.loadFile("./new.html"); }, }, ]; ``` 2、点击打开浏览器 `shell` 模块提供了集成其他桌面客户端的关联功能. ```js const { BrowserWindow, Menu, shell } = require("electron"); const template = [ { label: "csdn", click() { // 点击打开浏览器 shell.openExternal("https://www.4399.com/"); }, }, ]; ``` ## 5.3 抽离菜单定义 创建 menu.js,将 main.js 里面的菜单部分代码移入 menu.js ```js // menu.js const { BrowserWindow, Menu } = require("electron"); // 定义自定义菜单 const template = [ { label: "文件", submenu: [ { label: "新建窗口", // 自定义菜单点击事件 click: () => { const newMainWindow = new BrowserWindow({ width: 300, height: 300, }); newMainWindow.loadFile("./src/new.html"); }, }, ], }, { label: "编辑", submenu: [ { label: "新建窗口", }, ], }, ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); ``` ```js // main.js require("./menu"); ``` ## 5.4 自定义顶部菜单 - 通过 frame 创建无边框窗口 效果图 ![avatar](./readme_img/3.jpg) ```js const { app, BrowserWindow } = require("electron"); app.on("ready", () => { new BrowserWindow({ width: 800, height: 800, // 创建无边框窗口 frame: false, }); }); ``` - 自定义窗口 ```html
``` ```css * { margin: 0; padding: 0; } .custom-menu { height: 50px; width: 100%; background: pink; } .custom-menu ul { list-style: none; } .custom-menu ul li { float: left; width: 50px; line-height: 50px; text-align: center; margin-left: 10px; } ``` 重要!!!!!!!!!!! ```css /* 实现整体菜单拖拽 */ .custom-menu { -webkit-app-region: drag; } /*取消li菜单拖拽 */ .custom-menu li { -webkit-app-region: no-drag; } ``` ## 5.5 点击创建新窗口 ```js // html
  • 新建窗口
  • ; // js // remote 通过remote使用主进程的方法 const { remote: { BrowserWindow }, } = require("electron"); const newWindow = document.querySelector(".new-window"); newWindow.onclick = function () { new BrowserWindow({ width: 200, height: 300, }); }; ``` 老版本:能够在 html 中使用 node 方法 ```js const mainWindow = new BrowserWindow({ width: 800, height: 500, webPreferences: { // 开启node模块 nodeIntegration: true, // 开启remote模块 enableRemoteModule: true, }, }); ``` 新版本:能够在 html 中使用 node 方法 ```js // 1.首先在项目中通过npm安装它 cnpm i -S @electron/remote // 2.在主进程中初始化@electron/remote模块,然后才能从渲染器中使用 require('@electron/remote/main').initialize() require("@electron/remote/main").enable(myBrowserWindow.webContents) // 3.在主进程中开启remote,也就是webPreferences中添加 webPreferences: { // 开启渲染进程node模块 nodeIntegration: true, // 关闭上下文隔离 contextIsolation:false, // 开启渲染进程remote模块 enableRemoteModule: true, }, // 4.将代码require('electron').remote替换为require('@electron/remote') // 在渲染进程中: // 之前 const { BrowserWindow } = require('electron').remote // 17+版本 const { BrowserWindow } = require('@electron/remote') ``` ## 5.6 点页面打开浏览器 - html ```html
  • 关于我们
  • ``` - js ```js const { shell } = require("electron"); const goChrome = document.querySelector(".goChrome"); goChrome.onclick = (e) => { e.preventDefault(); shell.openExternal(e.target.href); }; ``` # 6. 打开对话框读取文件 ## 6.1 读取文件 - 定义点击事件 ```html ``` - 定义事件函数 打开对话框文档:https://www.electronjs.org/docs/api/dialog ```js // 打开对话框 function openFile() { const res = dialog.showOpenDialogSync({ title: "选择文件", buttonLabel: "哈哈", filters: [{ name: "Custom File Type", extensions: ["js"] }], }); const fileContent = fs.readFileSync(res[0]); dropEl.innerText = fileContent; } ``` ## 6.2 打开文件 - 定义点击事件 ```html ``` - 事件函数 ```js const { dialog } = require("@electron/remote"); const fs = require("fs"); // 打开选中文件 const openFile = () => { const fsRes = dialog.showSaveDialogSync({ // 窗口标题 title: "保存文件", // 按钮名 buttonLabel: "保存文件", // 保存类型,数组格式,可以配置多个 filters: [{ name: "index", extensions: ["js"] }], }); // 获取文件内容 const filesContent = fs.readFileSync(fsRes).toString(); }; ``` ## 6.3 保存文件 - 定义点击事件 ```html ``` - 事件函数 ```js const { dialog } = require("@electron/remote"); const fs = require("fs"); // 保存文件 const saveFile = function () { const res = dialog.showSaveDialogSync({ title: "保存文件", buttonLabel: "保存文件", filters: [{ name: "index", extensions: ["js"] }], }) // 将输入框的内容保存到文件 fs.writeFileSync(res, textareaEl.value); } ``` # 7. 定义快捷键 ## 7.1 主线程定义 - 引入 ```js const { globalShortcut } = require("electron"); ``` - 在 ready 中注册快捷键 ```js globalShortcut.register("CommandOrControl+X", () => { console.log("ctrl+X is pressed + 打印结果在命令行"); }) ``` - 定义快捷键最大、最小、关闭窗口 ```js // 窗口最小 globalShortcut.register("CommandOrControl+T", () => { myBrowserWindow.unmaximize(); }) // 关闭窗口 globalShortcut.register("CommandOrControl+H", () => { myBrowserWindow.close(); }) // 窗口最大 globalShortcut.register("CommandOrControl+M", () => { myBrowserWindow.maximize(); }) ``` ## 7.2 渲染进程定义 - 通过 remote 注册 ```js const { globalShortcut } = require("@electron/remote"); // 定义快捷键 globalShortcut.register("Ctrl+O", () => { console.log("ctrl+o") }) ``` # 8. 渲染进程和主线程通讯 - 定义按钮 ```html
  • ``` - 渲染进程事件函数 ```js const { ipcRenderer } = require("@electron/remote") // 点击窗口最大化 const maxWindow = function () { ipcRenderer.send("max-window") } // 点击窗口最小化 const minWindow = function () { ipcRenderer.send("min-window") } // 点击窗口关闭 const closeWindow = function () { ipcRenderer.send("close-window") } ``` - 主线程定义事件 ```js // 监听自定义事件 // 最大 ipcMain.on("max-window", (event, arg) => { myBrowserWindow.maximize() }) // 最小 ipcMain.on("min-window", (event, arg) => { myBrowserWindow.unmaximize() }) // 关闭 ipcMain.on("close-window", (event, arg) => { myBrowserWindow.close() }) ``` - 渲染进程传参 ```js const minWindow = function () { ipcRenderer.send("min-window","第二个参数是传递给主线程的参数") } ``` - 主线程接收参数 ```js ipcMain.on("min-window", (event, arg) => { // arg是接收的参数 console.log(arg) // 打印结果是:第二个参数是传递给主线程的参数 myBrowserWindow.unmaximize(); }); ``` # 09. electron 打包 - 安装 electron-packager ```js cnpm i electron-packager -D ``` - package.json添加打包任务 ```js // 报错,原因不明。。。。 "build": "electron-packager ./ HelloWorld --platform=win32 --arch=x64 --out ./outApp --overwrite --icon=./favicon.ico" ``` # 10 .electron 结合VUE框架开发 - 利用 vue 脚手架初始化项目 - 在项目中安装 electron cnpm i electron -S - 添加 electron 启动配置 ```js "main": "electronMain.js",// 新增的 "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "electron": "electron ." // 新增的 }, ``` - 配置 main.js ```js const { app, BrowserWindow } = require("electron") // 创建窗口 app.on("ready", () => { const mainWindow = new BrowserWindow({ width: 800, height: 600, }) }) ``` - 加载 vue 项目 ```js const { app, BrowserWindow } = require("electron") // 创建窗口 app.on("ready", () => { const mainWindow = new BrowserWindow({ width: 800, height: 600, }) mainWindow.loadURL("http://localhost:8000"); }) ``` # 11 .electron 结合REACT框架开发 - 在项目中安装 electron cnpm i electron -S - 添加 electron 启动配置.. 和vue一样..........不写了.........