网站建设英文专业术语,辽宁朝阳网站建设公司,h5响应式网站上海,常德seo快速排名概述
Electron chromium nodejs native API#xff0c;也就是将node环境和浏览器环境整合到了一起#xff0c;这样就构成了桌面端#xff08;chromium负责渲染、node负责操作系统API等#xff09;
流程模型
预加载脚本#xff1a;运行在浏览器环境下#xff0c;但是…概述
Electron chromium nodejs native API也就是将node环境和浏览器环境整合到了一起这样就构成了桌面端chromium负责渲染、node负责操作系统API等
流程模型
预加载脚本运行在浏览器环境下但是也能访问部分node API
初始化项目
先创建一个vue3vite的项目然后在项目当中安装electron。具体命令就是这样
npm create vitelatest vue-electron
cd vue-electron
npm i
npm i electron -D构建Electron项目
在package.json文件当中修改和添加type和main配置electron脚本运行在node环境下所以type要设置为commonjs然后main指向electron运行的入口文件再将启动命令加进去这样就可以通过 npm run start 来启动electron座面应用了 type: commonjs,main: electron/main/index.js// 启动命令start: electron .,编写electron/main/index.js。通过BrowserWindow创建一个浏览器窗口然后可以通过loadURL加载一个网页或者通过loadFile加载一个html文件进行渲染。然后还可以通过初始化监听去创建对应的窗口和关闭窗口的时候去退出electron。
const { app, BrowserWindow } require(electron)
const createWindow () {const win new BrowserWindow({width: 800,height: 600})win.loadURL(http://localhost:5173/);// win.loadFile(index.html)}
app.whenReady().then(() {createWindow()app.on(activate, () {if (BrowserWindow.getAllWindows().length 0) createWindow()})
})
app.on(window-all-closed, () {console.log(在关闭一个应用的所有窗口后让它退出);// 在关闭一个应用的所有窗口后让它退出if (process.platform darwin) {app.quit();}
});github 仓库地址https://github.com/lizuoqun/vue-electron.git 窗口常用方法
在win【BrowserWindow】对象当中会有一些常用的方法这里简单列出来一下完整的在这BrowserWindow Object API
getAllWindows所有打开的窗口的数组getFocusedWindow此应用程序中当前获得焦点的窗口fromBrowserView通过给定的视图返回对应的窗口close关闭窗口maximize最大化窗口unmaximize取消窗口最大化还有最小化、全屏、聚焦、背景、阴影、透明等等用的时候可以再去文档里面找一下对应的方法调用
命令合并
在这里是vue3和electron项目都在一起并且是直接访问5137端口加到桌面端的这个时候可以通过 npm-run-all 这个包可以将命令进行合并。先npm install npm-run-all这个包然后改一下下面的启动脚本通过 npm run deva 就可以直接启动vue3和electron项目了。
{scripts: {dev: vite,build: vue-tsc -b vite build,preview: vite preview,start: electron .,deva: npm-run-all --parallel dev start},
}预加载脚本
预加载脚本通过进行配置在electron入口文件中进行配置这里配置了一个同目录下的preload作为先进行加载的js脚本。
其中对于 WebPreferences Object 对象的配置可以看这个官方文档的配置其中有几个比较常用的
devTools boolean 是否开启 DevToolspreload string 预加载的脚本文件地址nodeIntegration boolean 是否启用Node integration 是否可以使用 Node.js 功能的配置contextIsolation boolean 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本. 默认为 true。 nodeIntegration设置为true后require is not define。需要设置contextIsolation为false const win new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, preload.js)}});扩展
这里来一个简单的electron当中的预加载脚本看一下并且进行扩展下
contextBridge API 上下文桥梁其他更多详细的配置可以参考官方文档下面只说一下使用到的 在隔离的上下文中创建一个安全的、双向的、同步的桥梁。 exposeInMainWorld方法
contextBridge.exposeInMainWorld(apiKey, api)
apiKey string - 将 API 注入到 窗口 的键。 API 将可通过 window[apiKey] 访问。api any - 你的 API可以是什么样的以及它是如何工作的相关信息如下。
const { contextBridge } require(electron)
/*** 在预处理的过程当中不能直接将值给绑定到window对象上再取值* 虽然预加载脚本与其所附着的渲染器在共享着一个全局 window 对象* 但并不能从中直接附加任何变动到 window 之上因为 contextIsolation 是默认的。* 所以在preload当中window.myAPI { desktop: true } 设置了myAPI但是在render当中获取不到console.log(window.myAPI)*/
contextBridge.exposeInMainWorld(versions, {node: () process.versions.node,chrome: () process.versions.chrome,electron: () process.versions.electron,
})因为这个脚本是预加载的在项目启动之后就会执行并且他里面的数据都是直接绑定在window对象上那么在这个项目里面其他的地方就可以直接使用了比方说在vue代码当中使用
这里不能通过模版插值直接写的原因很简单在vue里面只会去加载setup里面的数据但是versions是window的所以要在js里面用
script setup langts
import {onMounted} from vue;onMounted(() {const information document.getElementById(info) as HTMLDivElement;information.innerText 本应用正在使用 Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), 和 Electron (v${versions.electron()});
});
/scripttemplatediv idinfo/divdivversions: {{ versions }}/div
/template进程通信
概述
Electron 继承了来自 Chromium 的多进程架构网页浏览器的基本架构是单个浏览器进程控制不同标签页进程以及整个应用程序的生命周期。这样可以避免单个浏览器的无响应不会影响到整个浏览器。
Electron 应用的大致工作流程是启动APP——主进程创建window——win加载页面渲染进程
Electron 应用程序将控制两种类型的进程主进程和渲染器进程。
主进程渲染进程是啥
主进程 ipcMain
是应用的核心在应用启动时运行并在整个应用的生命周期中保持活动状态主要功能 创建和管理应用程序窗口管理窗口生命周期使用原生API
渲染进程
是应用的用户界面部分渲染线程运行在 Chromium 内核中可以像 Web 浏览器一样加载和呈现网页主要功能 一个应用可以有多个渲染进程Windows 中展示的界面通过渲染进程表现每个窗口都是一个独立的渲染线程无法直接操作原生API
渲染进程到主进程单向通信
在这里借用预加载脚本进行通信这里演示一下直接以vue3页面作为渲染进程然后通过preload预加载脚本传递到electron入口也就是主进程。
script setup langts
const renderToMainProcess () {electronApi.setTitle(渲染进程);
};
/script然后这个方法是在预加载脚本preload.js通过exposeInMainWorld进行绑定在window对象上的所以在上面可以直接使用
contextBridge.exposeInMainWorld(electronApi, {// 渲染器进程到主进程的通信单向通信setTitle: (title) ipcRenderer.send(set-title, title)
});在最后可以在electron入口当中拿到这个数据。这里就有问题了这是怎么知道触发了setTitle方法 ipcMainAPI在这 ipcRenderer是一个 EventEmitter 的实例。 当在主进程中使用时它处理从渲染器进程网页发送出来的异步和同步信息。 从渲染器进程发送的消息将被发送到该模块。 在ipcMain当中可以通过on、once等方法来监听ipcRenderer发送的事件。这就类比一个bus事件总线从ipcRenderer发的set-title事件之后从ipcMain当中拦截监听这个事件并且指定对应的回调来处理后续操作。
event他是一个 IpcMainEvent 对象。在这个可以直接通过点去获取里面的属性其中sender WebContent - 返回发送消息的 webContents然后通过 fromWebContents() 方法找到对应的窗口对象最后通过setTitle设置标题补充直接用win.setTitle其实也是一样的效果这是因为这个渲染进程和主进程是在同一个页面上的所以效果其实是一样的。因为 win 对象是在创建窗口时定义的它代表了整个窗口而不是特定的渲染进程。而我们需要的是找到发送消息的特定渲染进程对应的窗口对象
const createWindow () {const win new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, preload.js)}});ipcMain.on(set-title, (event, title) {const webContents event.sender;const ipcWin BrowserWindow.fromWebContents(webContents);ipcWin.setTitle(title);// win.setTitle(title)});win.loadURL(http://localhost:5173/);
};渲染进程到主进程双向通信
在主进程入口当中添加以下代码这里模拟的效果是在vue当中点击按钮后通过electron主进程打开文件系统选择文件选择文件之后拿到文件的路径之后再传递给渲染进程vue进行显示。
dialog API在这
显示用于打开和保存文件、警报等的本机系统对话框showOpenDialog打开这是一个异步的所以给他加了async和await变成同步他对应的也有一个showOpenDialogSync同步方法。Promise成功包含的数据 canceled boolean - 对话框是否被取消。filePaths string[] - 用户选择的文件路径的数组. 如果对话框被取消这将是一个空的数组。因为前面调用showOpenDialog方法的时候没有给他设置multiSelections参数文件多选这里直接取数组下标0也就是文件的路径了。 ipcMain.handle为一个invokeable的IPC 添加一个handler。 每当一个渲染进程调用 ipcRenderer.invoke(channel, ...args) 时这个处理器就会被调用。
async function handleFileOpen () {const { canceled, filePaths } await dialog.showOpenDialog({})if (!canceled) {return filePaths[0]}
}app.whenReady().then(() {ipcMain.handle(dialog:openFile, handleFileOpen)createWindow();app.on(activate, () {if (BrowserWindow.getAllWindows().length 0) createWindow();});
});在预加载脚本当中把dialog:openFile给定义下。这里用的是invoke表示通过 channel 向主过程发送消息并异步等待结果。拿到这一步就实现了主进程和渲染进程的双向通信机制和单向通信进行对比的区别在于单向通信使用到的send和on是单向传递理解成on和emit就可以了只能单向传递。而双向通信通过invoke和handle就像是一个监听和异步等待的效果每一个事件都会在ipcRenderer当中异步等待响应结果得到结果之后直接响应给渲染进程也就完成了双向通信
contextBridge.exposeInMainWorld(electronApi, {// 渲染器进程到主进程的通信双向通信openFile: () ipcRenderer.invoke(dialog:openFile)
});最后就是在vue渲染进程当中进行触发
script setup langts
import {ref} from vue;const renderToMainSingleProcess () {electronApi.setTitle(渲染进程);
};let filePath ref()
const renderToMainMultiProcess async () {filePath.value await window.electronApi.openFile()
};
/scripttemplatediv渲染进程-主进程通信/divel-button typeprimary clickrenderToMainSingleProcess单向/el-buttonel-button typeprimary clickrenderToMainMultiProcess双向/el-buttondiv双向通信的文件路径为:{{ filePath }}/div
/template主进程到渲染进程
在electron主进程当中添加一个menu菜单项这里通过webContents.send发送消息 const menu Menu.buildFromTemplate([{label: app.name,submenu: [{click: () win.webContents.send(update-counter, 1),label: 加一},{click: () win.webContents.send(update-counter, -1),label: 减一}]}]);Menu.setApplicationMenu(menu);预加载脚本暴露
contextBridge.exposeInMainWorld(electronApi, {// 主进程向渲染器进程发送消息onUpdateCounter: (callback) ipcRenderer.on(update-counter, (_event, value) callback(value)),counterValue: (value) ipcRenderer.send(counter-value, value)
});最后在渲染进程当中调用即可实现效果在这里的onUpdateCounter相对于一个回调触发在主进程当中调用update-counter之后会通过预加载暴露的方法到渲染进程这个渲染进程可以理解成一个监听器得到监听结果之后就可以拿到改变的值了。 补充然后这里的渲染进程和主进程的通信看前面的就好了也就是预加载脚本通过send发送在主进程当中通过ipcMain.on得到发送的消息 script setup langts
import {ref} from vue;let counter ref(0);
const mainToRender () {window.electronApi.onUpdateCounter((value) {const oldValue Number(counter.value);const newValue oldValue value;counter.value newValue.toString();window.electronApi.counterValue(newValue);});
};
/scripttemplateel-button typeprimary clickmainToRender主进程-渲染进程通信/el-buttondivCurrent value {{ counter }}/div
/template遇见的问题
问题一-32601
开启了控制台报错win.webContents.openDevTools();
{code:-32601,message:Autofill.enable wasnt found}异常信息在打开了控制台的时候会报这个错误但是并不影响实际使用这个持续可以看一下Electron GitHub issues
问题二Authors is required
An unhandled rejection has occurred inside Forge:
Error: Failed with exit code: 1
Output:
ڳԴӡweb_electron.nuspecɳ
Authors is required.
Description is required.可以看到这个的报错是Authors和Description都是必填的这个在package.json文件当中可能在初始化项目时没有填这两项这两项是必填的补充一下即可
打包之后在out目录下会有改exe文件exe文件名对应的是项目名称out\web-electron-win32-x64到这里也就完成了electron的打包了这个exe文件就可以直接在电脑上打开了。
打包
electron-build打包
这里安装electron-builder需要安装在开发环境当中
npm i electron-builder -D而后在package.json里面添加build配置这里简化些下面是需要添加的打包配置。打包后在dist目录下的exe直接安装即可
{scripts: {build-win: electron-builder},build: {productName: Electron,appId: com.modify,copyright: by modify,asar: true,win: {icon: electron/logo.ico},nsis: {oneClick: false,allowElevation: true,allowToChangeInstallationDirectory: true,installerIcon: electron/logo.ico,uninstallerIcon: electron/logo.ico,installerHeaderIcon: electron/logo.ico,createDesktopShortcut: true,createStartMenuShortcut: true,shortcutName: APP,runAfterFinish: true}}
}