在 Vue3 + Electron 中使用预加载脚本(preload)

文章目录

      • 一、什么是预加载脚本(preload),为什么我们需要它
      • 二、通过预加载脚本暴露相关 API 至渲染进程
        • 1、实现获取系统默认桌面路径功能
        • 2、向剪切板写入内容
        • 3、使用系统默认浏览器访问目标 url
        • 4、使用文件选择对话框
      • 三、参考资料

一、什么是预加载脚本(preload),为什么我们需要它

根据 Electron 官方提供的相关说明,我们可以将预加载脚本理解成是主进程和渲染进程间的桥梁。通常出于安全性的角度考虑,我们使用预加载脚本来安全地将 Node.js 模块或第三方库的 API 暴露至渲染进程中。

有时,我们可能为了在渲染进程中使用 Node.js 相关模块而关闭上下文隔离和为页面集成 Node.js 环境,但是这种方式官方并不推荐:

// 不推荐
const mainWindow = new BrowserWindow({webPreferences: {// 关闭上下文隔离contextIsolation: false,// 为页面集成 Node.js 环境nodeIntegration: true,}
})mainWindow.loadURL('https://example.com')

官方推荐的使用预加载脚本(preload)暴露相关 API,以使用 Node.js 的模块功能:

// 推荐
const mainWindow = new BrowserWindow({webPreferences: {preload: path.join(app.getAppPath(), 'preload.js')}
})mainWindow.loadURL('https://example.com')

关于预加载脚本的更多介绍参见:https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-preload
关于安全方面的更多介绍参见:https://www.electronjs.org/zh/docs/latest/tutorial/security

二、通过预加载脚本暴露相关 API 至渲染进程

实现目标:

  • 获取系统默认桌面路径功能
  • 向剪切板写入内容
  • 使用系统默认浏览器访问目标 url
  • 使用文件选择对话框

项目通过 electron-vite-vue 构建,详情可见:https://blog.csdn.net/qq_45897239/article/details/138490747

准备工作,在主进程 main.ts 文件中导入 preload 相关文件:

// electron/main.ts
function createWindow() {win = new BrowserWindow({width: 1200,height: 700,minWidth: 885,minHeight: 580,icon: path.join(process.env.VITE_PUBLIC, "electron-vite.svg"),webPreferences: {// 导入 preload 相关文件preload: path.join(__dirname, "preload.mjs"),},// 隐藏菜单栏 按 Alt 键显示autoHideMenuBar: true,});// 程序启动后开启 开发者工具// win.webContents.openDevTools();// 关闭菜单栏// Menu.setApplicationMenu(null);if (VITE_DEV_SERVER_URL) {win?.loadURL(VITE_DEV_SERVER_URL);} else {win?.loadFile(path.join(RENDERER_DIST, "index.html"));}
}
1、实现获取系统默认桌面路径功能

preload.ts 文件中通过 contextBridge 对外暴露自定义 API。

// electron/preload.ts
import { ipcRenderer, contextBridge } from "electron";contextBridge.exposeInMainWorld("electronAPI", {// 获取系统默认桌面路径getDesktopPath: async () => {try {return await ipcRenderer.invoke("get-desktop-path");} catch (error) {console.error("Failed to get desktop path:", error.message);}},...
});

ipcRenderer.invoke 允许渲染进程向主进程发送事件或消息,并且接收主进程返回的数据。

可以直接在主进程中使用 ipcMain.handle() 监听渲染进程发送来的消息:

// electron/main.ts
import { app, ipcMain } from "electron";
...
app.whenReady().then(async () => {try {...createWindow();// get-desktop-path => 获取系统桌面路径ipcMain.handle("get-desktop-path", () => {return app.getPath("desktop");});} catch (error) {console.error("Failed to start server:", error);}
});

调用 API 获取系统桌面路径:

<script setup lang="ts">
onMounted(async () => {// 获取系统桌面路径const res = await window.electronAPI.getDesktopPath();console.log(res);
});
</script>

注意: 可能会出现 ts 报错

属性“electronAPI”在类型“Window & typeof globalThis”上不存在。你是否指的是“Electron”?ts-plugin(2551)
electron.d.ts(12, 19): 在此处声明了 "Electron"

解决方案

vite-env.d.ts 中追加以下内容即可:

declare interface Window {electronAPI: any
}
2、向剪切板写入内容

定义相关 API:

// electron/preload.ts
import { ipcRenderer, contextBridge } from "electron";contextBridge.exposeInMainWorld("electronAPI", {// 向剪切板写入内容clipboardWriteText: async (text) => {try {await ipcRenderer.invoke("write-to-clipboard", text);} catch (error) {console.error("Failed to write to clipboard:", error.message);}},,...
});

主进程中监听:

// electron/main.ts
import { app, ipcMain, clipboard } from "electron";
...
app.whenReady().then(async () => {try {...// write-to-clipboard => 向剪切板写入内容ipcMain.handle("write-to-clipboard", (event, text) => {clipboard.writeText(text);});} catch (error) {console.error("Failed to start server:", error);}
});

使用:

<script setup lang="ts">
// 向剪切板写入内容
const copyLink = (text) => {window.electronAPI.clipboardWriteText(text);
};
</script>
3、使用系统默认浏览器访问目标 url

定义相关 API:

// electron/preload.ts
import { ipcRenderer, contextBridge } from "electron";contextBridge.exposeInMainWorld("electronAPI", {// 使用系统默认浏览器访问目标 urlopenBrowserByUrl: async (url) => {try {await ipcRenderer.invoke("open-browser-by-url", url);} catch (error) {console.error("Failed to open browser:", error.message);}},...
});

主进程中监听:

// electron/main.ts
import { app, ipcMain, shell } from "electron";
...
app.whenReady().then(async () => {try {...// open-browser-by-url => 使用系统默认浏览器访问目标 urlipcMain.handle("open-browser-by-url", async (event, url) => {await shell.openExternal(url);});} catch (error) {console.error("Failed to start server:", error);}
});

使用:

<script setup lang="ts">
// 使用系统默认浏览器访问目标 url
const goToLink = (url) => {window.electronAPI.openBrowserByUrl(url);
};
</script>
4、使用文件选择对话框

定义相关 API:

// electron/preload.ts
import { ipcRenderer, contextBridge } from "electron";contextBridge.exposeInMainWorld("electronAPI", {// 打开文件保存对话框 返回文件保存路径openFileSaveDialog: async (path) => {try {return await ipcRenderer.invoke("open-save-dialog",path);} catch (error) {console.error("Failed to open save dialog:", error.message);}},...
});

此处需要将文件对话框设置为顶层窗口,否则用户关闭应用程序后,该窗口依然存在。由于将对话框设置为顶层对话框需要win实例,所以使用函数方式导出初始化。设置为顶层对话框后,防止对话框被多次打开和未关闭对话框时的其他窗口操作。

可以在 electron 文件夹下创建一个 ipcHandlers.ts 文件,该文件内放置主进程需要监听的渲染进程发送来的消息,后续再导入 main.ts 主进程文件中。

// electron/ipcHandlers.ts
import { app, ipcMain, dialog, BrowserWindow } from "electron";// 可以在此文件内放置需要监听的来自渲染进程的消息
// get-desktop-path => 获取系统桌面路径
ipcMain.handle("get-desktop-path", () => {...
});export function initIpcHandlerDialog(win: BrowserWindow) {// open-save-dialog => 打开文件保存对话框ipcMain.handle("open-save-dialog", async (event, path) => {try {// 打开保存文件对话框const result = await dialog.showOpenDialog(win, {// 对话框标题title: "选择文件保存目录",// 确认按钮buttonLabel: "选择目录",// 默认文件路径defaultPath: app.getPath("desktop"),// 只允许选择文件夹properties: ["openDirectory"],// 文件过滤器,定义可以选择哪些类型的文件filters: [{ name: "All Files", extensions: ["*"] }]});if (result) {if (result.canceled) {console.log("用户取消了保存操作");// 如果用户取消了保存操作,则返回之前的保存路径,如若为空,则使用默认值if (!path) {path = app.getPath("desktop");}return path;} else {const filePath = result.filePaths[0];console.log("用户选择了保存路径:", filePath);return filePath;}}} catch (error) {console.log("文件对话框打开失败:" + error);// 获取桌面默认路径并返回return app.getPath("desktop");}});
}

在主进程中导入:

// electron/main.ts
import { app, BrowserWindow, ipcMain } from "electron";
...
// 导入相关功能模块
import "./ipcHandlers.ts";
import { initIpcHandlerDialog } from "./ipcHandlers.ts";...app.whenReady().then(async () => {try {...createWindow();// 初始化对话框,将弹出对话框设置为顶层状态initIpcHandlerDialog(win);} catch (error) {console.error("Failed to start server:", error);}
});

使用:

<script setup lang="ts">
// 打开文件保存对话框
const openSaveDialog = async () => {const defaultPath = 'D:/Desktop'const path = await window.electronAPI.openFileSaveDialog(defaultPath);
};
</script>

该方法传递了一个 defaultPath 参数,用于处理当用户点击了取消文件选择对话框时,使用的默认文件保存路径。

效果展示:

效果展示

三、参考资料

  • electron - ipcRenderer
  • electron - preload
  • electron - security

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

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

相关文章

负载测试和功率分析中负载箱的重要作用

在负载测试和功率分析中&#xff0c;负载箱扮演着至关重要的角色。以下是负载箱在这两个方面的重要作用&#xff1a; 一、负载测试中的重要作用 模拟实际负载条件&#xff1a; 负载箱能够模拟各种复杂的负载条件&#xff0c;包括电阻性负载、电感性负载、电容性负载等&#x…

【HarmonyOS开发】弹窗交互(promptAction )

实现效果 点击按钮实现不同方式的弹窗showToast showDialog showActionMenu 代码实现 1.引入’ohos.promptAction’ import promptAction from ohos.promptAction;2.通过promptAction 实现系统既定的弹窗 import promptAction from ohos.promptAction;Entry Component st…

Spring-Spring、IoC、DI、注解开发

1、Spring是什么 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。 Spring整体架构 Spring优点&#xff1a; Spring属于低侵入设计。IOC将对象之间的依赖关系交给Spring,降低组件之间的耦合&#xff0c;实现各个层之间的解耦&#xff0c;让我们更专注于业务…

数据库内核研发学习之路(三)创建postgres内置函数

本章之前已经讲明白了我们的postgres如何进行编译安装&#xff0c;这是很重要的一步&#xff0c;接下来就是学会对postgres进行小的改动&#xff0c;然后保证依然能够顺利编译安装运行&#xff01; 本章续讲内容如何创建一个内置函数。 1、内置函数和用户自定义函数的区别 熟…

如何在所有docker命令前加上一个sudo

如果当前登录用户不是root不用&#xff0c;使用docker命令的时候&#xff0c;需要在前面加上一个sudo 提升权限。 但是每次都加&#xff0c;就感觉特别的麻烦&#xff0c;如何简化呢&#xff1f; 解决办法 打开你的shell配置文件&#xff08;例如&#xff0c;如果你使用bash&am…

多媒体软件开发选择Animate软件还是Unity3D软件?

以下内容可能有一些片面&#xff0c;因为多媒体软件开发平台有很多&#xff0c;因为接触Animate和Unity3D比较多&#xff0c;所以这里仅对这两款进行分析&#xff01; Animate软件与Unity3D软件都是经常在多媒体展馆中用来制作互动展示内容的&#xff0c;对于这两种开发平台&a…

Java爬虫安全策略:防止TikTok音频抓取过程中的请求被拦截

摘要 在当今互联网时代&#xff0c;数据采集已成为获取信息的重要手段。然而&#xff0c;随着反爬虫技术的不断进步&#xff0c;爬虫开发者面临着越来越多的挑战。本文将探讨Java爬虫在抓取TikTok音频时的安全策略&#xff0c;包括如何防止请求被拦截&#xff0c;以及如何提高…

园区道路车辆智能管控视频解决方案,打造安全畅通的园区交通环境

一、背景需求分析 随着企业园区的快速发展和扩张&#xff0c;道路车辆管理成为了保障园区秩序、提升运营效率及确保员工安全的重要任务。针对这一需求&#xff0c;旭帆科技TSINGSEE青犀提出了一种企业园区道路车辆管控的解决方案&#xff0c;通过整合视频监控、智能识别等技术…

LVS+Nginx高可用集群---搭建高可用集群负载均衡

1.LVS简介 Lvs(Linux Virtual Server)&#xff1a;使用集群&#xff0c;对于整个用户来说是透明&#xff0c;用户访问的时候是单个高性能的整体。道理与nginx类似 LVS网络拓扑图&#xff1a;是基于四层。 用户通过浏览器发送请求&#xff0c;然后到达LVS.Lvs根据相应算法将…

【TensorRT】Yolov5-DeepSORT 目标跟踪

Yolov5-DeepSORT-TensorRT 本项目是 Yolo-DeepSORT 的 C 实现&#xff0c;使用 TensorRT 进行推理 &#x1f680;&#x1f680;&#x1f680; 开源地址&#xff1a;Yolov5_DeepSORT_TensorRT&#xff0c;求 star⭐ ~ 引言 ⚡ 推理速度可达25-30FPS&#xff0c;可以落地部署&…

南京邮电大学统计学课程实验2 用EXCEL进行参数估计假设检验 指导

一、实验描述 实验目的 1、学会用Excel进行参数估计&#xff1b; 2、学会用Excel进行z检验-双样本平均差检验&#xff1b; 实验环境 实验中使用以下软件和硬件设备 &#xff08;1&#xff09;Windows XP操作系统&#xff1b; &#xff08;2&#xff09;PC机、EXCEL软件&…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 卢小姐的生日礼物(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测…

【Vue3】4个比较重要的设计模式!!

大家好,我是CodeQi! 一位热衷于技术分享的码仔。 在我投身于前端开发的职业生涯期间,曾有一次承接了一个大型项目的维护工作。此项目运用的是 Vue 框架,然而其代码结构紊乱不堪,可维护性极度糟糕😫。 这使我深刻领会到,理解并运用 Vue 中的重要设计模式是何等关键! …

一个引发openssl崩溃问题案例

1 背景 最近用libevent写了一个https代理功能&#xff0c;在调研的时候&#xff0c;遇到了一个项目用到了本地多个openssl库引发的ssl握手崩溃问题。 2 开发环境 项目库版本号依赖项libeventlibevent-2.1.8-stableopenssl 1.1openssl1.0u / 1.1.1w / 3.3.1...... 3 问题现象…

vue3表格使用拖拽排序

拖拽排序 实现效果实现步骤拖拽排序功能的完整代码 实现效果 实现步骤 先安装sortable.js库使用的vue文件中引入 import Sortablejs from ‘sortablejs’在进入页面后创建sortable实例在提交后端时可获取到排序后的最新table列表数据 sortable.js文档 拖拽排序功能的完整代码 …

mars3d实现GraphicLayer获取当前相机视角内的可视点位(矢量数据

效果&#xff1a; mars3d实现GraphicLayer获取当前相机视角内的可视点位&#xff08;矢量数据 相关依赖api&#xff1a; 1. map.getExtent(); 提取地球当前视域边界,示例&#xff1a;{ xmin: 70, xmax: 140, ymin: 0, ymax: 55, height: 0, } 2.graphicLayer.eachGraphic遍…

小程序-2(WXML数据模板+WXSS模板样式+网络数据请求)

目录 1.WXML数据模板 数据绑定 事件绑定 小程序中常用的事件 事件对象的属性列表 target和currentTarget的区别 bindtap的语法格式 在事件处理事件中为data中的数据赋值 事件传参与数据同步 事件传参 bindinput的语法绑定事件 文本框和data的数据同步 条件渲染 w…

云计算数据中心(二)

目录 三、绿色节能技术&#xff08;一&#xff09;配电系统节能技术&#xff08;二&#xff09;空调系统节能技术&#xff08;三&#xff09;集装箱数据中心节能技术&#xff08;四&#xff09;数据中心节能策略和算法研究&#xff08;五&#xff09;新能源的应用&#xff08;六…

Qt会议室项目

在Qt中编写会议室应用程序通常涉及到用户界面设计、网络通信、音频/视频处理等方面。以下是创建一个基本会议室应用程序的步骤概述&#xff1a; 项目设置&#xff1a; 使用Qt Creator创建一个新的Qt Widgets Application或Qt Quick Application项目。 用户界面设计&#xff1…

一个用于管理多个 Node.js 版本的安装和切换开源工具

大家好&#xff0c;今天给大家分享一个用于管理多个Node.js版本的工具 NVM&#xff08;Node Version Manager&#xff09;&#xff0c;它允许开发者在同一台机器上安装和使用不同版本的Node.js&#xff0c;解决了版本兼容性问题&#xff0c;为开发者提供了极大的便利。 在开发环…