基于electron25+vite4创建多窗口|vue3+electron25新开模态窗体

在写这篇文章的时候,查看了下electron最新稳定版本由几天前24.4.0升级到了25了,不得不说electron团队迭代速度之快!

前几天有分享一篇electron24整合vite4全家桶技术构建桌面端vue3应用示例程序。

https://www.cnblogs.com/xiaoyan2017/p/17436076.html

这次继续接着上次项目,主要介绍electron25结合vue3技术实现创建多开窗口及窗口间主/渲染进程通信知识。

随着electron快速更新,结合vite的高效构建运行速度,现在新开一个独立窗口,打开速度极快。

electron官网主进程模块BrowserWindow用于创建一个新窗口的方法,提供了非常丰富的API操作用法。

BrowserWindow | Electron

复制代码

// In the main process.
const { BrowserWindow } = require('electron')const win = new BrowserWindow({ width: 800, height: 600 })// Load a remote URL
win.loadURL('https://github.com')// Or load a local HTML file
win.loadFile('index.html')

复制代码

如果每次都new一个BrowserWindow窗口,显得有些笨拙且复杂。今天要分享的是封装BrowserWindow方法,只需传入配置参数,即可快速生成一个独立窗口。

复制代码

createWin({title: '关于About.vue',route: '/about',width: 600,height: 400,background: '#fafffa',resize: true
})

复制代码

新建一个windows/index.js文件。

复制代码

/*** 封装多窗口管理器* @author YXY*/const { app, BrowserWindow, ipcMain } = require('electron')
const { join } = require('path')process.env.ROOT = join(__dirname, '../../')const isDevelopment = process.env.NODE_ENV == 'development'
// const winURL = isDevelopment ? 'http://localhost:3000/' : join(__dirname, 'dist/index.html')
const winURL = isDevelopment ? process.env.VITE_DEV_SERVER_URL : join(process.env.ROOT, 'dist/index.html')// 配置参数
const defaultConfig = {id: null,               // 窗口唯一idbackground: '#fff',     // 背景色route: '',              // 路由地址urltitle: '',              // 标题data: null,             // 传入数据参数width: '',              // 窗口宽度height: '',             // 窗口高度minWidth: '',           // 窗口最小宽度minHeight: '',          // 窗口最小高度x: '',                  // 窗口相对于屏幕左侧坐标y: '',                  // 窗口相对于屏幕顶端坐标resize: true,           // 是否支持缩放maximize: false,        // 最大化窗口isMultiWin: false,      // 是否支持多开窗口isMainWin: false,       // 是否主窗口parent: '',             // 父窗口(需传入父窗口id)modal: false,           // 模态窗口(模态窗口是浮于父窗口上,禁用父窗口)alwaysOnTop: false      // 置顶窗口
}class MultiWindows {constructor() {// 主窗口this.mainWin = null// 窗口组this.winLs = {}// ...}winOpts() {return {// 窗口图标icon: join(process.env.ROOT, 'resource/shortcut.ico'),backgroundColor: '#fff',autoHideMenuBar: true,titleBarStyle: 'hidden',width: 1000,height: 640,resizable: true,minimizable: true,maximizable: true,frame: false,show: false,webPreferences: {contextIsolation: true, // 启用上下文隔离(为了安全性)(默认true)// nodeIntegration: false, // 启用Node集成(默认false)preload: join(process.env.ROOT, 'resource/preload.js'),// devTools: true,// webSecurity: false}}}// 创建新窗口createWin(options) {const args = Object.assign({}, defaultConfig, options)console.log(args)// 判断窗口是否存在for(let i in this.winLs) {if(this.getWin(i) && this.winLs[i].route === args.route && !this.winLs[i].isMultiWin) {this.getWin(i).focus()return}}let opt = this.winOpts()if(args.parent) {opt.parent = this.getWin(args.parent)}if(typeof args.modal === 'boolean') opt.modal = args.modalif(typeof args.resize === 'boolean') opt.resizable = args.resizeif(typeof args.alwaysOnTop === 'boolean') opt.alwaysOnTop = args.alwaysOnTopif(args.background) opt.backgroundColor = args.backgroundif(args.width) opt.width = args.widthif(args.height) opt.height = args.heightif(args.minWidth) opt.minWidth = args.minWidthif(args.minHeight) opt.minHeight = args.minHeightif(args.x) opt.x = args.xif(args.y) opt.y = args.yconsole.log(opt)// 创建窗口对象let win = new BrowserWindow(opt)// 是否最大化if(args.maximize && args.resize) {win.maximize()}this.winLs[win.id] = {route: args.route, isMultiWin: args.isMultiWin}args.id = win.id// 加载页面let $urlif(!args.route) {if(process.env.VITE_DEV_SERVER_URL) {// 打开开发者调试工具// win.webContents.openDevTools()$url = process.env.VITE_DEV_SERVER_URL}else {$url = winURL}}else {$url = `${winURL}#${args.route}`}win.loadURL($url)/*if(process.env.VITE_DEV_SERVER_URL) {win.loadURL($url)}else {win.loadFile($url)}*/win.webContents.openDevTools()win.once('ready-to-show', () => {win.show()})win.on('close', () => win.setOpacity(0))// 初始化渲染进程win.webContents.on('did-finish-load', () => {// win.webContents.send('win-loaded', '加载完成~!')win.webContents.send('win-loaded', args)})}// 获取窗口getWin(id) {return BrowserWindow.fromId(Number(id))}// 获取全部窗口getAllWin() {return BrowserWindow.getAllWindows()}// 关闭全部窗口closeAllWin() {try {for(let i in this.winLs) {if(this.getWin(i)) {this.getWin(i).close()}else {app.quit()}}} catch (error) {console.log(error)}}// 开启主进程监听ipcMainListen() {// 设置标题ipcMain.on('set-title', (e, data) => {const webContents = e.senderconst wins = BrowserWindow.fromWebContents(webContents)wins.setTitle(data)// const wins = BrowserWindow.getFocusedWindow()// wins.setTitle('啦啦啦')})// 是否最大化(方法一)/*ipcMain.on('isMaximized', e => {const win = BrowserWindow.getFocusedWindow()e.sender.send('mainReplay', win.isMaximized())})*/// 是否最大化(方法二)ipcMain.handle('isMaximized', (e) => {const win = BrowserWindow.getFocusedWindow()return win.isMaximized()})ipcMain.on('min', e => {const win = BrowserWindow.getFocusedWindow()win.minimize()})ipcMain.handle('max2min', e => {const win = BrowserWindow.getFocusedWindow()if(win.isMaximized()) {win.unmaximize()return false}else {win.maximize()return true}})ipcMain.on('close', (e, data) => {// const wins = BrowserWindow.getFocusedWindow()// wins.close()this.closeAllWin()})// ...}
}module.exports = MultiWindows

复制代码

在主进程入口background.js文件引入封装窗口。

复制代码

const { app, BrowserWindow, ipcMain } = require('electron')
const { join } = require('path')const MultiWindows = require('./src/windows')// 屏蔽安全警告
// ectron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'const createWindow = () => {let window = new MultiWindows()window.createWin({isMainWin: true})window.ipcMainListen()
}app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) createWindow()})
})app.on('window-all-closed', () => {if (process.platform !== 'darwin') app.quit()
})

复制代码

在主进程中做一个ipcMain监听,用来创建独立窗口。

ipcMain.on('win-create', (event, args) => this.createWin(args))

新建windows/action.js文件,处理渲染器进程到主进程的异步通信,可以发送同步或异步的消息到主进程,也可以接收主进程发送的消息。

复制代码

/*** 创建新窗口* @param {object} args | {width: 640, height: 480, route: '/home'}*/
export function createWin(args) {window.electronAPI.send('win-create', args)
}/*** 设置窗口* @param {string} type | 'show'/'hide'/'close'/'min'/'max'/'max2min'/'restore'/'reload'* @param {number} id*/
export function setWin(type, id) {window.electronAPI.send('win-' + type, id)
}/*** 创建登录窗口*/
export function loginWin() {createWin({isMainWin: true,title: '登录',route: '/login',width: 550,height: 320,resize: false,alwaysOnTop: true,})
}

复制代码

在vue页面中调用上面封装的方法。

复制代码

<template><div class="home">...<Button type="success" @click="openWin">打开Manage窗口(设置parent)</Button><Button type="success" @click="openWin1">打开Me窗口(设置resizable/isMultiWin)</Button><Button type="success" @click="openWin2">打开User窗口</Button></div>
</template><script>
import { winCfg, createWin } from '@/windows/action'export default {name: 'Home',setup() {const openWin = () => {MessageBox.confirm('提示', '确定打开Manage页面吗? 【设置parent属性】', {callback: action => {if(action == 'confirm') {createWin({title: 'Manage.vue',route: '/manage',width: 600,height: 400,background: '#09f',parent: winCfg.window.id,// modal: true})}else if(action == 'cancel') {Message.info('您已取消!')}}})}const openWin1 = () => {// 左上角// let posX = 0// let posY = 0// 右下角let posX = window.screen.availWidth - 850let posY = window.screen.availHeight - 600MessageBox.confirm('提示', '确定打开Me页面吗?', {callback: action => {if(action == 'confirm') {createWin({title: 'Me.vue',route: '/me?name=Andy',width: 850,height: 600,x: posX,y: posY,background: 'yellow',resize: false,isMultiWin: true,maximize: true})}else if(action == 'cancel') {Message.info('您已取消!')}}})}const openWin2 = () => {MessageBox.confirm('提示', '确定打开User页面吗?', {callback: action => {if(action == 'confirm') {createWin({title: 'User.vue',route: '/user',width: 700,height: 550,minWidth: 300,minHeight: 300,data: {name: 'Andy',age: 20},background: 'green',isMultiWin: true})}else if(action == 'cancel') {Message.info('您已取消!')}}})}// ...return {openWin,openWin1,openWin2,// ...}}
}
</script>

复制代码

设置 frame: false 创建无边框窗口。

设置 -webkit-app-region: drag 来实现自定义拖拽区域。设置后的按钮操作无法响应其它事件,只需设置 -webkit-app-region: no-drag 即可实现响应事件。

electron+vite提供的一些环境变量。

process.env.NODE_ENV 
process.env.VITE_DEV_SERVER_URL

在开发环境,加载vite url,生产环境,则加载vite build出来的html。

Ok,综上就是electron25+vite4结合构建跨端应用的一些分享,希望对大家有所帮助哈~~

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

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

相关文章

7.JavaScript-vue

1 JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;我们需要给他注入灵魂&#xff0c;所以接下来我们需要学习JavaScript&#xff0c;这门语言会让我们的页面能够和用户进行交互。 1.1 介绍 通过代码/js效果演示提供资料进行效果演…

2023 彩虹全新 SUP 模板,卡卡云模板修复版

2023 彩虹全新 SUP 模板&#xff0c;卡卡云模板&#xff0c;首页美化&#xff0c;登陆页美化&#xff0c;修复了 PC 端购物车页面显示不正常的问题。 使用教程 将这俩个数据库文件导入数据库&#xff1b; 其他的直接导入网站根目录覆盖就好&#xff1b; 若首页显示不正常&a…

游戏逆向中的 NoClip 手段和安全应对方式

文章目录 墙壁边界寻找碰撞 NoClip 是一种典型的黑客行为&#xff0c;允许你穿过墙壁&#xff0c;所以 NoClip 又可以认为是避免碰撞体积的行为 墙壁边界 游戏中设置了碰撞体作为墙壁边界&#xff0c;是 玩家对象 和墙壁发生了碰撞&#xff0c;而不是 相机 玩家对象有他的 X…

操作系统初探 - 进程的概念

目录 预备知识 冯诺依曼和现代计算机结构 操作系统的理解 进程和PCB的概念 PCB中的信息 查看进程信息的指令 - ps pid 进程状态 预备知识 在学习操作系统之前我们需要先了解一下如下的预备知识。 冯诺依曼和现代计算机结构 美籍匈牙利科学家冯诺依曼最先提出“程序存…

MARS: An Instance-aware, Modular and Realistic Simulator for Autonomous Driving

● MARS: An Instance-aware, Modular and Realistic Simulator for Autonomous Driving&#xff08;基于神经辐射场的自动驾驶仿真器&#xff09; ● https://github.com/OPEN-AIR-SUN/mars ● https://arxiv.org/pdf/2307.15058.pdf ● https://mp.weixin.qq.com/s/6Ion_DZGJ…

paddle2.3-基于联邦学习实现FedAVg算法-CNN

目录 1. 联邦学习介绍 2. 实验流程 3. 数据加载 4. 模型构建 5. 数据采样函数 6. 模型训练 1. 联邦学习介绍 联邦学习是一种分布式机器学习方法&#xff0c;中心节点为server&#xff08;服务器&#xff09;&#xff0c;各分支节点为本地的client&#xff08;设备&#…

cad图纸如何防止盗图(一个的制造设计型企业如何保护设计图纸文件)

在现代企业中&#xff0c;设计图纸是公司的重要知识产权&#xff0c;关系到公司的核心竞争力。然而&#xff0c;随着技术的发展&#xff0c;员工获取和传播设计图纸的途径越来越多样化&#xff0c;如何有效地防止员工复制设计图纸成为了企业管理的一大挑战。本文将从技术、管理…

QT常用控件介绍

QT信号与槽机制 connect (A,SIGNLA(aaa())&#xff0c;B, SLOT(bbb()))&#xff1b; GUI继承简介 布局管理器 垂直布局水平布局网格布局表单布局 输出控件 Label: 标签Text Browser: 文本浏览器Graphics View : 图形视图框架Calendar Widget: 日历控件LCD Number: 液晶字体数…

VSCode 在部分 Linux 设备上终端和文本编辑器显示文本不正常的解决方法

部分Linux设备上运行VSCode时&#xff0c;发现文本编辑器的缩放不明显&#xff0c;终端字体间距过大等。 这里以Kali Linux为例&#xff0c;其他Linux发行版请选择对应的系统内置的等宽字体 我们依次打开 设置 -> 外观 -> 字体 这里我们可以发现&#xff0c;Kali Linux默…

数据结构与算法----递归

1、迷宫回溯问题 package com.yhb.code.datastructer.recursion&#xffe5;5;public class MiGong {public static void main(String[] args) {// 先创建一个二维数组&#xff0c;模拟迷宫// 地图int[][] map new int[8][7];// 使用1 表示墙// 上下全部置为1for (int i 0; i…

SpringBoot详解

文章目录 1. Xml 和 JavaConfig1.1 什么是 JavaConfig1.2 JavaConfig 配置容器1.3 ImportResource1.4 PropertyResource 2. 注解SpringBootApplication3.Spring Boot 核心配置文件3.1 yaml格式3.2 .yml 文件3.3 多环境配置3.4 Spring Boot 自定义配置3.4.1 Value 注解 3.5 注解…

浏览器指定DNS

edge--设置 https://dns.alidns.com/dns-query

计算机毕设 大数据B站数据分析与可视化 - python 数据分析 大数据

文章目录 0 前言1 课题背景2 实现效果3 数据获取4 数据可视化5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做…

有时候,使用 clang -g test.c 编译出可执行文件后,发现 gdb a.out 进行调试无法读取符号信息,为什么?

经过测试&#xff0c;gdb 并不是和所有版本的 llvm/clang 都兼容的 当 gdb 版本为 9.2 时&#xff0c;能支持 9.0.1-12 版本的 clang&#xff0c;但无法支持 16.0.6 版本的 clang 可以尝试使用 LLVM 专用的调试器 lldb 我尝试使用了 16.0.6 版本的 lldb 调试 16.0.6 的 clan…

kafka客户端应用参数详解

一、基本客户端收发消息 Kafka提供了非常简单的客户端API。只需要引入一个Maven依赖即可&#xff1a; <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.13</artifactId><version>3.4.0</version></depend…

Java后端模拟面试,题集①

1.Spring bean的生命周期 实例化 Instantiation属性赋值 Populate初始化 Initialization销毁 Destruction 2.Spring AOP的创建在bean的哪个时期进行的 &#xff08;图片转载自Spring Bean的完整生命周期&#xff08;带流程图&#xff0c;好记&#xff09;&#xff09; 3.MQ如…

2023年哪款PDF虚拟打印机好用?

PDF文档想必大家都不陌生&#xff0c;在工作中经常会用到该格式的文档&#xff0c;那么有哪些方法能制作PDF文档呢&#xff1f;一般都是借助PDF虚拟打印机的&#xff0c;那么有哪些好用的软件呢&#xff1f; pdfFactory不仅为用户提供了丰富的PDF文档生成、打印功能&#xff0…

【JavaEE】JavaScript

JavaScript 文章目录 JavaScript组成书写方式行内式内嵌式外部式&#xff08;推荐写法&#xff09; 输入输出变量创建动态类型基本数据类型数字类型特殊数字值 String转义字符求长度字符串拼接布尔类型undefined未定义数据类型null 运算符条件语句if语句三元表达式switch 循环语…

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石③

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石③ 第十九章 驱动程序基石③19.5 定时器19.5.1 内核函数19.5.2 定时器时间单位19.5.3 使用定时器处理按键抖动19.5.4 现场编程、上机19.5.5 深入研究&#xff1a;定时器的内部机制19.5.6 深入研究&#xff1a;找到系统滴答 1…

数学建模Matlab之检验与相关性分析

只要做C题基本上都会用到相关性分析、一般性检验等&#xff01; 回归模型性能检验 下面讲一下回归模型的性能评估指标&#xff0c;用来衡量模型预测的准确性。下面是每个指标的简单解释以及它们的应用情境&#xff1a; 1. MAPE (平均绝对百分比误差) 描述: 衡量模型预测的相对…