当前位置: 首页 > 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 不希望某…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...