quasar electron mode如何打包无边框桌面应用程序

article/2025/8/11 9:42:26

预览

请添加图片描述

开源项目Tokei Kun

一款简洁的周年纪念app,现已发布APK(安卓)和 EXE(Windows)
项目仓库地址:Github Repo
应用下载链接:Github Releases

Preparation for Electron

quasar dev -m electron# passing extra parameters and/or options to
# underlying "electron" executable:
quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox
# when on Windows and using Powershell:
quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox

基本命令

quasar dev -m electron

指定以 Electron 模式运行启动 Quasar 开发服务器

传递参数

Linux/MacOS 语法:

quasar dev -m electron -- --no-sandbox --disable-setuid-sandbox
  • --: 这个符号表示后面的参数是传递给底层 Electron 可执行文件的,而不是 Quasar CLI

Windows PowerShell 语法:

quasar dev -m electron '--' --no-sandbox --disable-setuid-sandbox
  • 在 PowerShell 中需要用引号包裹 --

参数解释

–no-sandbox

禁用 Chromium 的沙盒(sandbox)安全机制沙盒是一种安全功能,限制应用程序对系统资源的访问禁用沙盒可能会降低安全性,但在某些环境下是必要的

–disable-setuid-sandbox

禁用 setuid 沙盒setuid 是一种 Unix 权限机制,允许程序以更高权限运行,在某些 Linux 系统上,如果无法使用 setuid 沙盒,需要禁用此功能

Frameless Electron Window

安装依赖

npm install --save @electron/remote

修改electron-main.js

import { app, BrowserWindow, nativeTheme } from 'electron'
import { initialize, enable } from '@electron/remote/main' // <-- add this
import path from 'path'initialize() // <-- add this// ...mainWindow = new BrowserWindow({width: 1000,height: 600,useContentSize: true,frame: false // <-- add thiswebPreferences: {sandbox: false // <-- to be able to import @electron/remote in preload script// ...}
})enable(mainWindow.webContents) // <-- add thismainWindow.loadURL(process.env.APP_URL)// ...

[!warning]
官方文档中import { initialize, enable } from ‘@electron/remote/main’
这里我出现了报错
改为import { initialize, enable } from '@electron/remote/main/index.js’正常运行

![[import error.png]]
quasar issue:Electron dev app @electron/remote error · Issue #17971 · quasarframework/quasar

[!success] 成功
接下里我们需要处理窗口拖拽以及最小化、最大化与关闭应用

预加载脚本

由于我们无法直接从渲染线程访问 Electron,需要通过 electron 预加载脚本( src-electron/main-process/electron-preload.js )提供必要功能。因此我们将其修改为:

//src-electron/main-process/electron-preload
import { contextBridge } from 'electron'
import { BrowserWindow } from '@electron/remote'contextBridge.exposeInMainWorld('myWindowAPI', {minimize () {BrowserWindow.getFocusedWindow().minimize()},toggleMaximize () {const win = BrowserWindow.getFocusedWindow()if (win.isMaximized()) {win.unmaximize()} else {win.maximize()}},close () {BrowserWindow.getFocusedWindow().close()}
})

处理窗口拖拽

当我们使用无边框窗口(仅限无边框!)时,还需要为用户提供在屏幕上移动应用窗口的方式。为此,您可以使用 q-electron-dragq-electron-drag--exception Quasar CSS 辅助类。

[!TIPS] 提示
也许你可以在layout文件中为某些组件添加类q-electron-drag试试

该功能允许用户在屏幕上点击、按住并同时拖动鼠标时,拖拽应用程序窗口。

最小化、最大化与关闭应用

在某些vue文件(例如添加在MainLayout.vue中)
Template

<q-space /><q-btn dense flat icon="minimize" @click="minimize" />
<q-btn dense flat icon="crop_square" @click="toggleMaximize" />
<q-btn dense flat icon="close" @click="closeApp" />

[!TIP]
若觉得iconminimize不太习惯(位于底部),可以使用remove(竖直居中)
q-space的作用是将q-btn挤到右边

选项式

<script>
// We guard the Electron API calls with the optional chaining JS operator,
// but this is only needed if we build same app with other Quasar Modes
// as well (SPA/PWA/Cordova/SSR...)export default {setup () {function minimize () {window.myWindowAPI?.minimize()}function toggleMaximize () {window.myWindowAPI?.toggleMaximize()}function closeApp () {window.myWindowAPI?.close()}return { minimize, toggleMaximize, closeApp }}
}
</script>

组合式

<script setup>
// We guard the Electron API calls with the optional chaining JS operator,
// but this is only needed if we build same app with other Quasar Modes
// as well (SPA/PWA/Cordova/SSR...)function minimize() {if (process.env.MODE === 'electron') {window.myWindowAPI?.minimize()}
}function toggleMaximize() {if (process.env.MODE === 'electron') {window.myWindowAPI?.toggleMaximize()}
}function closeApp() {if (process.env.MODE === 'electron') {window.myWindowAPI?.close()}
}
</script>

Electron的 Unable to load preload script 报错解决方案-CSDN博客

Build

quasar build -m electron -d

附完整代码

electron-main.js

import { app, BrowserWindow, ipcMain } from 'electron'
import { initialize, enable } from '@electron/remote/main/index.js' // <-- add this
import path from 'node:path'
import os from 'node:os'
import { fileURLToPath } from 'node:url'initialize() // <-- add this
// needed in case process is undefined under Linux
const platform = process.platform || os.platform()const currentDir = fileURLToPath(new URL('.', import.meta.url))let mainWindowasync function createWindow () {/*** Initial window options*/mainWindow = new BrowserWindow({icon: path.resolve(currentDir, 'icons/icon.png'), // tray iconwidth: 1200,height: 900,useContentSize: true,frame: false,webPreferences: {sandbox: false, // 开启沙盒则preload脚本被禁用,所以得设为falsecontextIsolation: true,// More info: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/electron-preload-scriptpreload: path.resolve(currentDir,path.join(process.env.QUASAR_ELECTRON_PRELOAD_FOLDER, 'electron-preload' + process.env.QUASAR_ELECTRON_PRELOAD_EXTENSION))}})enable(mainWindow.webContents) // <-- add thisif (process.env.DEV) {await mainWindow.loadURL(process.env.APP_URL)} else {await mainWindow.loadFile('index.html')}if (process.env.DEBUGGING) {// if on DEV or Production with debug enabledmainWindow.webContents.openDevTools()} else {// we're on production; no access to devtools plsmainWindow.webContents.on('devtools-opened', () => {mainWindow.webContents.closeDevTools()})}mainWindow.on('closed', () => {mainWindow = null})
}app.whenReady().then(createWindow)app.on('window-all-closed', () => {if (platform !== 'darwin') {app.quit()}
})app.on('activate', () => {if (mainWindow === null) {createWindow()}
})

electron-preload.js

import { contextBridge } from 'electron'
import { BrowserWindow } from '@electron/remote/'contextBridge.exposeInMainWorld('myWindowAPI', {minimize () {BrowserWindow.getFocusedWindow().minimize()},toggleMaximize () {const win = BrowserWindow.getFocusedWindow()if (win.isMaximized()) {win.unmaximize()} else {win.maximize()}},close () {BrowserWindow.getFocusedWindow().close()}
})
/*** This file is used specifically for security reasons.* Here you can access Nodejs stuff and inject functionality into* the renderer thread (accessible there through the "window" object)** WARNING!* If you import anything from node_modules, then make sure that the package is specified* in package.json > dependencies and NOT in devDependencies** Example (injects window.myAPI.doAThing() into renderer thread):**   import { contextBridge } from 'electron'**   contextBridge.exposeInMainWorld('myAPI', {*     doAThing: () => {}*   })** WARNING!* If accessing Node functionality (like importing @electron/remote) then in your* electron-main.js you will need to set the following when you instantiate BrowserWindow:** mainWindow = new BrowserWindow({*   // ...*   webPreferences: {*     // ...*     sandbox: false // <-- to be able to import @electron/remote in preload script*   }* }*/

http://www.hkcw.cn/article/iKRQXhXkji.shtml

相关文章

Linux 中应用层自定义协议与序列化 -- 自定义协议概述,序列化和反序列化,Jsoncpp

目录 1. 应用层自定义协议概述 2. 序列化和反序列化 3. 重新理解 read, write, recv, send 以及 TCP 为什么支持全双工 4.Jsoncpp 4.1 Jsoncpp 的特性 4.2 使用 Jsoncpp 的序列化和反序列化 4.3 Json::Value 的介绍 4.3.1 构造函数 4.3.2 访问元素 4.3.3 类型检查 …

历年南京理工大学计算机保研上机真题

2025南京理工大学计算机保研上机真题 2024南京理工大学计算机保研上机真题 2023南京理工大学计算机保研上机真题 在线测评链接&#xff1a;https://pgcode.cn/school 求阶乘 题目描述 给出一个数 n n n ( 1 ≤ n ≤ 13 ) (1 \leq n \leq 13) (1≤n≤13)&#xff0c;求出它…

[JVM] JVM内存调优

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

当 Python 遇上 Go:Sponge 如何成为替代 Django/Flask 的理想选择

开篇&#xff1a;Python 老司机的自白 各位 Python 老铁们&#xff01;咱们写 Python 那叫一个"纵享丝滑"——动态类型玩到飞起&#xff0c;列表推导式秀得飞起&#xff0c;Django/Flask 一把梭&#xff0c;PyPI 库多到能砸死人&#xff01;是不是觉得自己就是代码界…

Flask与PostgreSQL交互教程

目录 1. 项目结构2. 环境准备2.1 安装依赖2.2 使用Docker启动PostgreSQL 3. 数据库配置3.1 环境变量配置3.2 数据库连接配置 4. 定义数据库模型5. 实现API接口5.1 创建用户5.2 获取所有用户5.3 获取单个用户5.4 更新用户5.5 删除用户 6. 运行应用7. API测试7.1 创建用户7.2 获取…

QT中sqlite多线程操作注意事项总结:安全性与效率的双重提升

QT中sqlite多线程操作注意事项总结&#xff1a;安全性与效率的双重提升 【下载地址】QT中sqlite多线程操作注意事项总结 本项目深入探讨了在Qt框架下进行SQLite多线程操作时可能遇到的四大关键问题&#xff0c;包括线程安全、数据库连接管理、信号与槽机制以及性能优化。通过详…

深入JVM:类加载器和双亲委派模型

目录 1. 什么是类加载器2. 类加载器的类型3. 双亲委派模型4. 类装载的过程加载验证准备解析初始化使用卸载 1. 什么是类加载器 如果想要了解什么是类加载器就需要清楚一个Java文件是如何运行的。我们可以看下图&#xff1a; 首先要知道操作系统是不能直接运行Java文件的&#…

【JVM —— 03 类的生命周期】

Java 类的生命周期指的是一个类从加载到内存到卸载出内存的整个过程。这一过程主要包括以下几个阶段&#xff1a; 加载&#xff08;Loading&#xff09;连接&#xff08;Linking&#xff09; 验证&#xff08;Verification&#xff09;准备&#xff08;Preparation&#xff09;…

Arthas简介及示例

一、什么是Arthas&#xff1f; Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方…

JVM考古现场(十七):鸿蒙初辟——从太极二进到混沌原初的编译天道

"此刻正是奇点编译的第3.1415926秒&#xff01;伏羲的算筹正在撕裂冯诺依曼架构的次元壁&#xff01;诸君请看——这JVM堆内存中正在孕育盘古的元神&#xff01;" 目录&#xff08;终极扩展&#xff09; 第一章&#xff1a;太极二进——内存模型的阴阳交缠 第二章&a…

JVM的组成

JVM 运行在操作系统之上 java二进制字节码文件的运行环境 JVM的组成部分 java代码在编写完成后编译成字节码文件通过类加载器 来到运行数据区,主要作用是加载字节码到内存 包含 方法区/元空间 堆 程序计数器,虚拟机栈,本地方法栈等等 随后来到执行引擎,主要作用是翻译字…

【java面试题】二进制(详解,一看就会)

二进制 1.什么是二进制 二进制是一种数值表示系统&#xff0c;它使用两个符号表示数字&#xff1a;0和1。它是计算机系统的基础&#xff0c;因为计算机使用二进制数来进行数据存储和处理。在二进制中&#xff0c;每一位代表一个2的幂次方&#xff0c;比如&#xff1a; 0 020…

Java 2.4 - JVM

一、Java 内存区域详解&#xff08;重点&#xff09; 本篇讨论的是 HotSpot 虚拟机 相比于 C 而言&#xff0c;程序员不需要对每个 new 操作都写对应的 delete / free 操作&#xff0c;这些操作我们会交给虚拟机去做。因此&#xff0c;如果不了解虚拟机的原理&#xff0c;一旦…

java面试-- 必问之jvm与性能优化(一)

问题一、 描述一下 JVM 加载 Class 文件的原理机制? JVM&#xff08;Java虚拟机&#xff09;加载Class文件的原理机制是Java程序运行的关键组成部分。这一过程涉及到多个阶段&#xff0c;确保Java程序能够跨平台运行&#xff0c;并动态地加载、解析和执行Java Class文件。以下…

JVM运行时数据区之虚拟机栈

【1】概述 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;&#xff0c;早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈&#xff0c;其内部保存一个个的栈帧&#xff08;Stack Frame&#xff09;&#xff0c;对应着一次次的Java方法调用。 栈是运行…

【Linux探索学习】第三十二弹——生产消费模型:基于阻塞队列和基于环形队列的两种主要的实现方法

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在前面我们已经学习了关于线程的主要知识&#xff0c;包括线程的基础知识以及线程的同步与互斥等内容&#xff0c;今天我们来学几个线程知…

复现FAST_LIVO2【Ubuntu 20.04.6 LTS】

目录 准备1 Ubuntu 和 ROS2 其他库2.1 PCL2.2 Eigen2.3 OpenCV 3 Sophus3.1 安装3.2 make报错 4 Vikit5 livox_ros_driver5.1 Livox-SDK5.2 livox_ros_driver FAST-LIVO2运行参考 准备 1 Ubuntu 和 ROS 依据开源介绍&#xff0c;Ubuntu 16.04~20.04。 复现版本为&#xff1a;…

【基于Ubuntu下Yolov5的目标识别】保姆级教程 | 虚拟机安装 - Ubuntu安装 - 环境配置(Anaconda/Pytorch/Vscode/Yolov5) |全过程图文by.Akaxi

目录 一.【YOLOV5算法原理】 1.输入端 2.Backbone 3.Neck 4.输出端 二&#xff0e;【系统环境】 1.虚拟机的安装与创建 2.安装Ubuntu操作系统 3.环境的配置 3.1.Ubuntu下Anacoda安装以及虚拟环境配置 3.2.Pytorch安装 3.3.Vscode安装 3.4.Yolov5源码及环境获取安装…

[已解决] 本地两台 win电脑 (以太网) 网线传输文件 - 局域网连接 (解决windows无法访问共享文件问题 - Windows 安全中心输入网络凭据 用户名/密码 不正确问题)

背景 由于要本地传输的数据比较大&#xff0c;大几百GB网盘传输慢&#xff0c;正好有网线&#xff0c;试着本地网线高速传输&#xff08;实测113MB/s&#xff09;踩了很多坑&#xff0c;想把亲测成功的经验分享出来帮助更多同学 目录 1 网线接入 2 设置两台电脑的IP地址 3 …

Docker(三):DockerFile

一、DockerFile介绍 1、DockerFile 介绍 DockerFile 是一种能够被Docker 程序解释的文件&#xff08;一般为了方便理解称之为“剧本”&#xff09;。 DockerFile 由一条一条的指令组成&#xff0c;并且有自己的书写格式和支持的命令。当我们需要在容器 镜像中指定自己额外的需…