Electron通过预加载脚本从渲染器访问Node.js

问题:如何实现输出Electron的版本号和它的依赖项到你的web页面上?

答案:在主进程通过Node的全局 process 对象访问这个信息是微不足道的。 然而,你不能直接在主进程中编辑DOM,因为它无法访问渲染器 文档 上下文。 它们存在于完全不同的进程!这是将 预加载 脚本连接到渲染器时派上用场的地方。预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window 和 document) 和 Node.js 环境。

1.创建预加载脚本 

在项目的src/preload/目录下创建一个名为 preload.js 的新脚本如下: 

const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('electronAPI', {onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value)),setTitle: (title) => ipcRenderer.send('set-title', title)
})

2.在主进程中引入

在主进程的background.js文件中,引入预加载脚本如下:

 // 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},

这里使用了两个Node.js概念:

  • __dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)。
  • path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。

我们使用一个相对当前正在执行JavaScript文件的路径,这样您的相对路径将在开发模式和打包模式中都将有效。

background.js文件 

'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},// webPreferences: {//   // Use pluginOptions.nodeIntegration, leave this alone//   // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info//   nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,//   contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     //await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}

 3.在主进程和渲染进程中使用预加载脚本

主进程中使用:

 ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})

 主进程完整脚本文件

'use strict'import { app, protocol, BrowserWindow, ipcMain, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }
])async function createWindow() {// Create the browser window.const win = new BrowserWindow({width: 800,height: 600,// 指定预加载脚本webPreferences: {// 启用上下文隔离contextIsolation: true,// 禁用 Node.js 集成,因为我们将通过预加载脚本来提供所需的功能nodeIntegration: false,// 禁用 remote 模块,出于安全考虑enableRemoteModule: false,// 设置预加载脚本preload: path.join(__dirname, "preload.js"),},// webPreferences: {//   // Use pluginOptions.nodeIntegration, leave this alone//   // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info//   nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,//   contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION// }})///ipcMain.on('set-title', (event, title) => {const webContents = event.senderconsole.log(`接收到渲染进程消息:`, title);event.reply('update-counter', title)})console.log(`path.join(__dirname, "preload.js")`, path.join(__dirname, "preload.js"));///if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)if (!process.env.IS_TEST) win.webContents.openDevTools()} else {createProtocol('app')// Load the index.html when not in developmentwin.loadURL('app://./index.html')}
}// Quit when all windows are closed.
app.on('window-all-closed', () => {// On macOS it is common for applications and their menu bar// to stay active until the user quits explicitly with Cmd + Qif (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()
})// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {// if (isDevelopment && !process.env.IS_TEST) {//   // Install Vue Devtools//   try {//     //await installExtension(VUEJS_DEVTOOLS)//   } catch (e) {//     console.error('Vue Devtools failed to install:', e.toString())//   }// }createWindow()
})// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {if (process.platform === 'win32') {process.on('message', (data) => {if (data === 'graceful-exit') {app.quit()}})} else {process.on('SIGTERM', () => {app.quit()})}
}

渲染进程中使用:

<template><div><div>接收主进程的消息{{ ShowData }}</div><button @click="sendToMain">Send Message to Main</button></div>
</template><script>
export default {data() {return {ShowData: 0,};},methods: {sendToMain() {const title = Math.round(Math.random() * 100);window.electronAPI.setTitle(title);},},mounted() {// 监听主进程的回复window.electronAPI.onUpdateCounter((value) => {console.log(`接收主进程的消息:`, value);this.ShowData = value;});},//   beforeDestroy() {//     // 在组件销毁前,移除事件监听器//  window.ipcRenderer.removeAllListeners("reply-from-main");//   },
};
</script>

注意:开发环境时主进程使用的是软件编译后dist_electron目录下的preload.js 预加载文件

 到这里在开发环境就能使用预加载脚本实现主进程和渲染进程通信了

4.在vue.config.js中进行electron打包配置

如果想在electron打包后的软件中仍然可以正常使用预加载脚本文件的话,必须在vue.config.js文件中进行相应的打包配置。

  pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//项目名,也是生成的安装文件名,即.exe"copyright": "Copyright © 2024",//版权信息"win": {//win相关配置// "icon": "./src/assets/icon.ico",//图标,当前图标在根目录下"target": [{"target": "nsis",//利用nsis制作安装程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一键安装"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。"allowToChangeInstallationDirectory": true, // 允许修改安装目录// "installerIcon": "./src/assets/icon.ico",// 安装图标// "uninstallerIcon": "./src/assets/icon.ico",//卸载图标// "installerHeaderIcon": "./src/assets/icon.ico", // 安装时头部图标"createDesktopShortcut": true, // 创建桌面图标"createStartMenuShortcut": true,// 创建开始菜单图标"shortcutName": "voloday_test", // 图标名称},}},},

vue.config.js文件 

const { defineConfig } = require('@vue/cli-service')
const path = require("path");
console.log(`path.join(__dirname,'preload.js')`, path.join(__dirname,'preload.js'));
module.exports = defineConfig({transpileDependencies: true,publicPath: './',pluginOptions: {electronBuilder: {removeElectronJunk: false,preload: './src/preload/preload.js',builderOptions: {"appId": "voloday_test","productName": "voloday_test",//项目名,也是生成的安装文件名,即.exe"copyright": "Copyright © 2024",//版权信息"win": {//win相关配置// "icon": "./src/assets/icon.ico",//图标,当前图标在根目录下"target": [{"target": "nsis",//利用nsis制作安装程序"arch": ["x64",//64位]}]},"nsis": {"oneClick": false, // 是否一键安装"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。"allowToChangeInstallationDirectory": true, // 允许修改安装目录// "installerIcon": "./src/assets/icon.ico",// 安装图标// "uninstallerIcon": "./src/assets/icon.ico",//卸载图标// "installerHeaderIcon": "./src/assets/icon.ico", // 安装时头部图标"createDesktopShortcut": true, // 创建桌面图标"createStartMenuShortcut": true,// 创建开始菜单图标"shortcutName": "voloday_test", // 图标名称},}},},})

源码:GitHub - 1t1824d/elctron29.0.0_node18.19.0_vuecli5.0.8_vue2 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/508354.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FreeRTOS学习笔记——FreeRTOS中断管理

精华总结&#xff1a; 中断优先级0为最高&#xff0c;任务优先级0为最低 中断优先级分组中为方便rtos管理4bit全部设置成抢占优先级 32单片机的中断管理是由3个寄存器完成&#xff08;名字忽略&#xff0c;具体功能忽略&#xff09;&#xff0c;三个寄存器都是32bit&#xff0c…

【JavaScript】手写 Promise(静态方法)

手写Promise-静态方法resolve 需求: 返回一个带有成功原因的Promise对象 HMPromise.resolve(new HMPromise((resolve, reject) > {// resolve(resolve)// reject(reject)// throw error })).then(res > {console.log(res:, res) }, err > {console.log(err:, err) …

Google Dremel和parquet的复杂嵌套数据结构表征方法解析

转载请注明出处。作者&#xff1a;archimekai 核心参考文献&#xff1a; Dremel: Interactive Analysis of Web-Scale Datasets 文章目录 引言复杂嵌套数据结构的无损表征问题Dremel论文中提出的表征方法parquet备注 引言 Dremel是Google的交互式分析系统。Google大量采用prot…

阅读笔记 | Transformers in Time Series: A Survey

阅读论文&#xff1a; Wen, Qingsong, et al. “Transformers in time series: A survey.” arXiv preprint arXiv:2202.07125 (2022). 这篇综述主要对基于Transformer的时序建模方法进行介绍。论文首先简单介绍了Transformer的基本原理&#xff0c;包括位置编码、多头注意力机…

01 MySQL之连接

1. 连接 1.0 基础认知 多表(主表)和一表(从表的区别): 多表一般是主表&#xff0c;一般存储主要数据&#xff0c;每个字段都可能存在重复值&#xff0c;没有主键&#xff0c;无法根据某个字段定位到准确的记录&#xff1b; 一表一般是从表&#xff0c;一般存储辅助数据&…

基础二分学习笔记

模板 : 个人倾向第一种 ; 整数二分 : 最大化查找 : 可行区域在左侧 : 查找最后一个<q的数的下标 : int find(int q){// 查找最后一个 < q 的下标 int l 0 , r n 1 ;while(l 1 < r){int mid l r >> 1 ;if(a[mid]<q) l mid ;else r mid ;}return…

如何限制一个账号只在一处登陆

大家好&#xff0c;我是广漂程序员DevinRock&#xff01; 1. 需求分析 前阵子&#xff0c;和问答群里一个前端朋友&#xff0c;随便唠了唠。期间他问了我一个问题&#xff0c;让我印象深刻。 他问的是&#xff0c;限制同一账号只能在一处设备上登录&#xff0c;是如何实现的…

第二篇【传奇开心果系列】Python的自动化办公库技术点案例示例:深度解读Pandas金融数据分析

传奇开心果博文系列 系列博文目录Python的自动化办公库技术点案例示例系列 博文目录前言一、Pandas 在金融数据分析中的常见用途和功能介绍二、金融数据清洗和准备示例代码三、金融数据索引和选择示例代码四、金融数据时间序列分析示例代码五、金融数据可视化示例代码六、金融数…

CUDA 中的线程组织

明朝那些事中有一句话&#xff1a;我之所以写徐霞客是想告诉你&#xff0c;所谓千秋霸业万古流芳&#xff0c;与一件事相比&#xff0c;其实都算不了什么&#xff0c;这件事情就是——用你喜欢的方式度过一生。 我们以最简单的 CUDA 程序&#xff1a;从 GPU 中输出 Hello World…

C++基于多设计模式下的同步异步日志系统day4

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 只要内容主要实现了同步日志消息…

Unreal触屏和鼠标控制旋转冲突问题

Unreal触屏和鼠标控制旋转冲突问题 鼠标控制摄像机旋转添加Input轴计算旋转角度通过轴事件控制旋转 问题和原因问题原因 解决办法增加触摸控制旋转代码触屏操作下屏蔽鼠标轴响应事件 鼠标控制摄像机旋转 通过Mouse X和Mouse Y控制摄像机旋转。 添加Input轴 计算旋转角度 通过…

外贸网站模板建站

测绘检测wordpress外贸主题 简洁实用的wordpress外贸主题&#xff0c;适合做测绘检测仪器设备的外贸公司使用。 https://www.jianzhanpress.com/?p5337 白马非马衣服WordPress外贸建站模板 白马非马服装行业wordpress外贸建站模板&#xff0c;适用于时间服装企业的官方网站…