当前位置: 首页 > news >正文

【前端】-【electron】

文章目录

  • 介绍
    • electron工作流程
    • 环境搭建
  • electron生命周期(app的生命周期)
  • 窗口尺寸
  • 窗口标题
  • 自定义窗口的实现
  • 阻止窗口关闭
  • 父子及模态窗口
  • 自定义菜单

介绍

electron技术架构:chromium、node.js、native.apis
在这里插入图片描述

electron工作流程

在这里插入图片描述
桌面应用就是运行在不同操作系统上的软件,软件中的功能是通过native.apis跟不同操作系统进行交互实现的,想实现什么功能调用响应的API即可
electron主要有两类进程:

  1. 主进程:main process
  2. 渲染进程:renderer process

当我们启动一个APP时,他首先会启动主进程,一般是main.js或index.js中的代码,主进程启动成功后会创建一个native ui,然后在nativeui里创建一个或多个Browse window,用于呈现界面(即web界面),每个Browse window可以看作是一个渲染进程,每个渲染进程相互独立,各自运行在自己的沙箱环境中,但是app在使用的过程中,不同窗口会进行交互,于是electron提供了IPC、RPC通信机制供窗口与窗口进行数据传输
在这里插入图片描述
只有主进程能操作原生API,能管理所有WEB界面,和这些web界面对应的渲染进程
在这里插入图片描述
渲染进程支持所有的DOM操作、node api的调用操作

环境搭建

package.json中main字段指定的文件就是app启动后,启动的主进程;script字段指定的是启动项目的命令
在这里插入图片描述

electron生命周期(app的生命周期)

ready:app初始化完成后会被调用一次,一般用于窗口初始化
dom-ready:一个窗口中的文本加载完成,与dom操作相关,有个webcontext对象可以调用
did-finsh-load:导航完成时触发,即选项卡的旋转器停止旋转时触发,且指派了onload事件。由webcontext调用
window-all-closed:所有窗口都被关闭时触发,如果我们没有监听这个方法,那么所有窗口关闭后,应用程序就默认退出,如果我们监听了这个方法,我们就可以自己决定所有窗口关闭后,应用程序是否退出,如果我们选择不退出,那么后续的before-quit、will-quit、quit都失效了
before-quit:在关闭窗口之前触发
will-quit:在窗口关闭并且应用退出时触发
quit:所有窗口被关闭时触发
closed:当窗口关闭时触发,此时应删除窗口引用

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({width: 800,height:400})mainWindow.loadFile('index.html')// webContents用于操作dommainWindow.webContents.on('did-finish-load',() => {console.log("33333------did-finish-load")})mainWindow.webContents.on('dom-ready',() => {console.log("22222------dom-ready")})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',() => {console.log("11111------ready")createWindow()
})app.on('window-all-closed',() => {console.log("44444------window-all-closed")
})app.on('before-quit',() => {console.log("55555------before-quit")
})app.on('will-quit',() => {console.log("66666------will-quit")
})app.on('quit',() => {console.log("77777------quit")
})

执行顺序:1——2——3——8——4——5——6——7

窗口尺寸

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({x:100,// 设置窗口显示的位置,距离左边的距离y:100,// 设置窗口显示的位置,距离右边的距离width: 800,height:400,maxHeight:600,// 窗口最大高度minHeight:200,// 窗口最小高度maxWidth:1000,// 窗口最大宽度minWidth:300,// 窗口最小宽度resizable:false// 是否允许缩放窗口,默认为true,可以缩放窗口,设为false})mainWindow.loadFile('index.html')mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

注意此时有个bug:窗口弹出来,然后有一段白屏时间,然后再出现内容,这是因为let mainWindow = new BrowserWindow()执行完成后就会显示出窗口来,此时窗口里面是没有内容的,我们设置show:false,让窗口创建好也不展示出来,然后加载index.html文件,加载完成后,监听窗口的ready-to-show方法,再把窗口展示出来

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({show:false,width: 800,height:400})mainWindow.loadFile('index.html')// 监听窗口已经准备好去展示了mainWindow.on('ready-to-show',()=>{mainWindow.show()})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

窗口标题

在这里插入图片描述

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({show:false,width: 800,height:400,frame: false,// 是否有边框transparent:true,// 窗体透明,只有frame: false时才生效icon:'lg.ico',// 图标title:'拉钩教育',// 窗口标题autoHideMenuBar: true// 隐藏菜单、选项卡})mainWindow.loadFile('index.html')// 监听窗口已经准备好去展示了mainWindow.on('ready-to-show',()=>{mainWindow.show()})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

需求:窗口里面提供一个按钮,点击按钮,再弹出一个窗口

ctr+r可以对应用进行重载
25版本后可以使用ipcMain和ipcRenderer实现新窗口

index.html代码如下:
在这里插入图片描述
版本一:主进程允许渲染进程使用BrowserWindow实现,main.js代码如下:

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({show:false,width: 800,height:400,webPreferences:{nodeIntegration:true,// 允许渲染进程使用node集成环境contextIsolation: false,// 如果nodeIntegration:true失效,那么需要添加这行代码 }})mainWindow.loadFile('index.html')// 监听窗口已经准备好去展示了mainWindow.on('ready-to-show',()=>{mainWindow.show()})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

index.js代码(index.html的js代码)如下:
在这里插入图片描述
版本二:主进程允许渲染进程使用remote实现,main.js代码如下:

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({show:false,width: 800,height:400,webPreferences:{enableRemoteModule:true//允许使用远程模式},autoHideMenuBar: true// 隐藏菜单、选项卡})mainWindow.loadFile('index.html')// 监听窗口已经准备好去展示了mainWindow.on('ready-to-show',()=>{mainWindow.show()})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

index.js代码(index.html的js代码)如下:

const { remote } = require('electron')
window.addEventListener('DOMContentLoaded',() => {// 点击按钮打开一个新窗口const oBtn = document.getElementsById('btn')oBtn.addEventListener('click',() => {// 创建窗口let indexWindow = new remote.BrowserWindow({width:200,height:200})indexWindow.loadFile('sub.html')indexWindow.on('close',() => {indexWindow = null})})
})

自定义窗口的实现

需求:点击窗口右上角的三个图标,分别执行相应操作
在这里插入图片描述
index.html代码如下,红框中为三个图标的代码
在这里插入图片描述
main.js中代码如下:

const { app, BrowserWindow } = require('electron')// 创建窗口
function createWindow() {let mainWindow = new BrowserWindow({show:false,width: 800,height:400,webPreferences:{nodeIntegration:true,// 允许渲染进程使用node集成环境contextIsolation: false,// 如果nodeIntegration:true失效,那么需要添加这行代码enableRemoteModule:true//允许使用远程模式},autoHideMenuBar: true// 隐藏菜单、选项卡})mainWindow.loadFile('index.html')// 监听窗口已经准备好去展示了mainWindow.on('ready-to-show',()=>{mainWindow.show()})mainWindow.on('close',() => {console.log("88888------close")mainWindow = null})
}app.on('ready',createWindow)app.on('window-all-closed',() => {console.log("window-all-closed")app.quit()
})

index.html的js代码写在index.js中,如下:

const { remote } = require('electron')
window.addEventListener('DOMContentLoaded',() => {// 利用remote可以获取当前窗口对象let mainWindow = remote.getCurrentWindow()// 获取元素添加点击操作的监听let aBtn = document.getElementsByClassName('windowTool')[0].getElementsByTagName('div')aBtn[0].addEventListener('click',() => {// 关闭窗口mainWindow.close()})aBtn[1].addEventListener('click',() => {// 最大化console.log(mainWindow.isMaximized())// 先判断当前窗口是不是最大化,如果是,则回到原来的大小,如果不是最大化,则最大化当前窗口if(!mainWindow.isMaximized()){mainWindow.maximize()// 让当前窗口最大化}else{mainWindow.restore()// 让当前窗口回到原来的大小}})aBtn[2].addEventListener('click',() => {// 最小化console.log(mainWindow.isMinimized())if(!mainWindow.isMaximized()){mainWindow.minimize()// 让当前窗口最小化}})
})

阻止窗口关闭

点击右上角的关闭按钮后,弹出浮窗提示用户是否关闭,若用户选择关闭,则关闭应用,否则关闭浮窗,index.html页面如下:
在这里插入图片描述
index.html中的js代码保存在index.js中,代码如下:

const { remote } = require('electron')
window.addEventListener('DOMContentLoaded',() => {// 监听mainWindow.close()window.onbeforeunload = function(){let oBox = document.getElementsByClassName('isClose')[0]oBox.style.display = 'block'// 弹窗出现let yseBtn = oBox.getElementsByTagName('span')[0]let noBtn = oBox.getElementsByTagName('span')[1]yseBtn.addEventListener('click', () => {// 此时关闭窗口需要用destory,// 因为onbeforeunload用于监听mainWindow.close(),如果这里还用mainWindow.close关闭的话,会陷入死循环mainWindow.destory()})noBtn.addEventListener('click', () => {oBox.style.display = 'none'// 去掉弹窗})}// 利用remote可以获取当前窗口对象let mainWindow = remote.getCurrentWindow()// 获取元素添加点击操作的监听let aBtn = document.getElementsByClassName('windowTool')[0].getElementsByTagName('div')aBtn[0].addEventListener('click',() => {// 关闭窗口mainWindow.close()})aBtn[1].addEventListener('click',() => {// 最大化console.log(mainWindow.isMaximized())// 先判断当前窗口是不是最大化,如果是,则回到原来的大小,如果不是最大化,则最大化当前窗口if(!mainWindow.isMaximized()){mainWindow.maximize()// 让当前窗口最大化}else{mainWindow.restore()// 让当前窗口回到原来的大小}})aBtn[2].addEventListener('click',() => {// 最小化console.log(mainWindow.isMinimized())if(!mainWindow.isMaximized()){mainWindow.minimize()// 让当前窗口最小化}})
})

父子及模态窗口

在这里插入图片描述
index.js代码如下:

const { remote } = require('electron')
window.addEventListener('DOMContentLoaded',() => {// 点击按钮打开一个新窗口const oBtn = document.getElementsById('btn')oBtn.addEventListener('click',() => {// 创建窗口let indexWindow = new remote.BrowserWindow({parent:remote.getCurrentWindow(),// 指定子窗口的父窗口是主线程的窗口modal:true,// 子窗口是模态化窗口,当子窗口出现时,父窗口不能游任何操作,也不能移动width:200,height:200})indexWindow.loadFile('sub.html')indexWindow.on('close',() => {indexWindow = null})})
})

自定义菜单

相关文章:

【前端】-【electron】

文章目录 介绍electron工作流程环境搭建 electron生命周期(app的生命周期)窗口尺寸窗口标题自定义窗口的实现阻止窗口关闭父子及模态窗口自定义菜单 介绍 electron技术架构:chromium、node.js、native.apis electron工作流程 桌面应用就是…...

Python中的类(Class)和对象(Object)

目录 一、引言 二、类(Class) 1、类的定义 2、类的实例化 三、对象(Object) 1、对象的属性 2、对象的方法 四、类和对象的继承和多态性 1、继承 2、多态性 五、类与对象的封装性 1、封装的概念 2、Python中的封装实现…...

dp-拦截导弹2

所有代码均来自于acwing中的算法基础课和算法提高课 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度, 但是以后每一发炮弹都不能高于前一发的高度。…...

初识动态规划算法(题目加解析)

文章目录 什么是动态规划正文力扣题第 N 个泰波那契数三步问题使用最小花费爬楼梯 总结 什么是动态规划 线性动态规划:是可以用一个dp表来存储内容,并且找到规律存储,按照规律存储。让第i个位置的值等于题目要求的答案 >dp表:dp表就是用一…...

Vue2.0与Vue3.0的区别

一、Vue2和Vue3的数据双向绑定原理发生了改变 Vue2的双向数据绑定是利用ES5的一个API,Object.definePropert()对数据进行劫持 结合 发布 订阅模式的方式来实现的。通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息…...

探索人工智能领域——每日20个名词详解【day6】

目录 前言 正文 总结 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于CSDN📚。 📣如需转载,请事先与我联系以…...

C++初阶 | [七] string类(上)

摘要:标准库中的string类的常用函数 C语言中,字符串是以\0结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(面向对象)的思想&#…...

Django总结

文章目录 一、Web应用Web应用程序的优点Web应用程序的缺点应用程序有两种模式C/S、B/S C/S 客户端/服务端局域网连接其他电脑的MySQL数据库1.先用其他电脑再cmd命令行ping本机ip2.开放MySQL的访问 B/S 浏览器/服务端基于socket编写一个Web应用 二、Http协议1.http协议是什么2.h…...

【qml入门系列教程】:qml QtObject用法介绍

作者:令狐掌门 技术交流QQ群:675120140 博客地址:https://mingshiqiang.blog.csdn.net/ 文章目录 QtObject 是 Qt/QML 中的一个基础类型,通常用作创建一个没有 UI 的(不渲染任何东西的)纯逻辑对象。可以使用它来组织代码、存储状态或者作为属性和方法的容器。 以下是如何…...

2分图匹配算法

定义 节点u直接无边,v之间无边,边只存在uv之间。判断方法:BFS染色法,全部染色后,相邻边不同色 无权二部图中的最大匹配 最大匹配即每一个都匹配上min(u, v)。贪心算法可能导致&…...

[EndNote学习笔记] 导出库中文献的作者、标题、年份到Excel

菜单栏Edit中,选择 Output Styles 在默认的 Annotated上进行修改,在Bibliography栏下的Templates中修改想要导出的格式 其中,每个粗体标题表示,针对不同的文献类型,设置相应的导出格式。一般为Journal Article&…...

SQL Sever 基础知识 - 数据查询

SQL Sever 基础知识 - 一、查询数据 一、查询数据第1节 基本 SQL Server 语句SELECT第2节 SELECT语句示例2.1 SELECT - 检索表示例的某些列2.2 SELECT - 检索表的所有列2.3 SELECT - 对结果集进行筛选2.4 SELECT - 对结果集进行排序2.5 SELECT - 对结果集进行分组2.5 SELECT - …...

Vue入门——v-on标签

文章目录 规则v-on 一、案例总结 规则 v-on 作用&#xff1a;为html标签绑定事件语法&#xff1a; v-on&#xff1a;事件名&#xff1a;“函数名”简写为 事件名“函数名” 注意&#xff1a;函数需要定义在methods选项内部 一、案例 我们给案件绑定一个单击事件 <!DOCTYPE…...

JVM:双亲委派(未完结)

类加载 定义 一个java文件从编写代码到最终运行&#xff0c;必须要经历编译和类加载的过程&#xff0c;如下图&#xff08;图源自b站视频up主“跟着Mic学架构”&#xff09;。 编译就是把.java文件变成.class文件。类加载就是把.class文件加载到JVM内存中&#xff0c;得到一…...

Leetcode 2661. 找出叠涂元素

Leetcode 2661. 找出叠涂元素题目 给你一个下标从 0 开始的整数数组 arr 和一个 m x n 的整数 矩阵 mat 。arr 和 mat 都包含范围 [1&#xff0c;m * n] 内的 所有 整数。从下标 0 开始遍历 arr 中的每个下标 i &#xff0c;并将包含整数 arr[i] 的 mat 单元格涂色。请你找出 a…...

vscode代码调试配置

C/C代码调试 点击 vscode左侧的 run and debug&#xff0c;新建launch.json 和 tasks.json&#xff0c;并进行配置如下 launch.json {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more informati…...

PTA 7-225 sdut-C语言实验- 冒泡排序中数据交换的次数

听说过冒泡排序么&#xff1f;一种很暴力的排序方法。今天我们不希望你用它来排序&#xff0c;而是希望你能算出从小到大冒泡排序的过程中一共进行了多少次数据交换。 输入格式: 输入数据的第一行为一个正整数 T &#xff0c;表示有 T 组测试数据。 接下来T行&#xff0c;每行…...

新的 BLUFFS 攻击导致蓝牙连接不再私密

蓝牙是一种连接我们设备的低功耗无线技术&#xff0c;有一个新的漏洞需要解决。 中间的攻击者可以使用新的 BLUFFS 攻击轻松窥探您的通信。 法国研究中心 EURECOM 的研究员 Daniele Antonioli 演示了六种新颖的攻击&#xff0c;这些攻击被定义为 BLUFFS&#xff08;蓝牙转发和…...

安全测试之推荐工具(一)

文章目录 一、前言二、Web安全&#xff08;一&#xff09;AppScan&#xff08;推荐&#xff09;&#xff08;二&#xff09;AWVS&#xff08;推荐&#xff09;&#xff08;三&#xff09;Burp Suite&#xff08;推荐&#xff09;&#xff08;四&#xff09;OWASP ZAP 三、主机安…...

final关键字

修饰 类&#xff0c;属性&#xff0c;方法&#xff0c;局部变量&#xff08;包括方法参数&#xff09; 类似c语言的const 使用方式&#xff1a; 1 不希望类被继承 用final类&#xff08;类很重要&#xff0c;担心别人重写/修改&#xff09; 2 不希望某…...

STM32 RTC实战:如何用纽扣电池实现断电时间保持(附完整代码)

STM32 RTC实战&#xff1a;如何用纽扣电池实现断电时间保持&#xff08;附完整代码&#xff09; 在工业控制、智能仪表和物联网设备中&#xff0c;精确的时间记录往往是系统可靠运行的关键。想象一下&#xff0c;当一台自动化设备突然断电后重启&#xff0c;如果无法准确恢复断…...

yuzu模拟器终极性能优化:突破帧率限制的完整指南

yuzu模拟器终极性能优化&#xff1a;突破帧率限制的完整指南 【免费下载链接】yuzu-downloads 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu-downloads 你是否正在为yuzu模拟器的卡顿问题而烦恼&#xff1f;游戏画面不流畅、帧率波动大、操作延迟明显&#…...

SkyWalking 9.7.0与Elasticsearch 8.17.4集成避坑指南:证书转换那些事儿

SkyWalking 9.7.0与Elasticsearch 8.17.4深度集成实战&#xff1a;证书转换与安全通信全解析 当分布式系统的可观测性需求遇上Elasticsearch 8.x强化的安全机制&#xff0c;SkyWalking集成过程中的证书问题往往成为技术人员的"拦路虎"。本文将带您穿透PEM与PKCS12的格…...

TradingAgents-CN:5分钟掌握AI金融分析终极指南

TradingAgents-CN&#xff1a;5分钟掌握AI金融分析终极指南 【免费下载链接】TradingAgents-CN 基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版 项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN 你是不是也曾经为投资决策而烦恼&…...

告别本地IDE!浏览器编程神器code-server的完整配置与权限避坑指南

告别本地IDE&#xff01;浏览器编程神器code-server的完整配置与权限避坑指南 你是否厌倦了在不同设备间同步开发环境的繁琐&#xff1f;或是受限于本地IDE的性能瓶颈&#xff1f;code-server的出现彻底改变了这一局面——它将强大的VS Code编辑器搬进浏览器&#xff0c;让你在…...

WordPress站长必看:Bricks Builder插件爆高危RCE漏洞(CVE-2024-25600),手把手教你自查与修复

WordPress站长紧急应对&#xff1a;Bricks Builder高危漏洞深度防护指南 当我在凌晨三点收到服务器异常流量告警时&#xff0c;第一反应是检查最近安装的插件——Bricks Builder。作为一款拥有超过50万活跃安装量的WordPress可视化建站工具&#xff0c;它刚刚被曝出CVSS评分9.8…...

用OpenCV和C++实现无人机影像自动匹配:从Moravec特征点到NCC相关系数的完整流程

无人机影像智能匹配实战&#xff1a;基于OpenCV的Moravec与NCC全流程解析 当无人机掠过一片待测区域时&#xff0c;它每秒能捕获数十张高分辨率影像。这些影像蕴含着丰富的地理信息&#xff0c;但如何让这些二维图片"对话"&#xff0c;构建出三维世界的数字孪生&…...

通义千问3-Reranker-0.6B问题解决:端口占用、模型加载失败的快速排查

通义千问3-Reranker-0.6B问题解决&#xff1a;端口占用、模型加载失败的快速排查 1. 为什么你的模型服务总是启动失败&#xff1f; 你满怀期待地部署了通义千问3-Reranker-0.6B&#xff0c;准备体验这个轻量级重排序模型的强大能力。你按照文档执行了启动命令&#xff0c;然后…...

s2-pro开源模型价值:Fish Audio专业音频团队技术沉淀公开

s2-pro开源模型价值&#xff1a;Fish Audio专业音频团队技术沉淀公开 1. 产品概述 s2-pro是Fish Audio开源的专业级语音合成模型镜像&#xff0c;代表了该团队在音频AI领域的技术沉淀。这个开源项目将专业级的语音合成能力以简单易用的方式提供给开发者&#xff0c;支持文本转…...

从像素到概念:如何用Python+OpenCV一步步提取图像的底层和高层特征

从像素到概念&#xff1a;PythonOpenCV实战图像特征提取全流程 引言&#xff1a;理解图像特征的层次性 当我们注视一张海滩照片时&#xff0c;视觉系统会经历从局部到整体的认知过程——首先捕捉海浪的纹理、沙粒的明暗&#xff0c;然后识别出遮阳伞、游泳者等独立物体&#xf…...