Electron从构建到打包exe应用

news2024/11/13 9:42:38

Electron从构建到打包程exe应用

  • Electron文档
  • 搭建
  • 网页装载到 BrowserWindow中
  • 定义全局对象
  • 进程之间通信
    • 渲染器进程到主进程(单向)
    • 渲染器进程到主进程(双向)
    • 主进程到渲染器进程
  • 打开调试器
  • 打包应用程序
  • 对代码进行签名

Electron文档

搭建

创建一个文件夹,在根目录执行以下几个命令

1.npm init
2.npm install electron --save-dev
3.根目录新增main.js文件,添加内容console.log("hellow!!")
4.package.json中更改
	"main": "main.js",
	"scripts":{
		"start": "electron .",  
	}

然后运行根目录执行命令npm run start
可以在命令行中看到hellow!!,此时项目算是跑通了
在这里插入图片描述

网页装载到 BrowserWindow中

1.根目录新增index.html文件,写添加html的默认代码等标签,并添加一个hellow

<!DOCTYPE html>
<body>
  <h1>Hello!!</h1> 
</body>

2.根目录新增main.js

const { app, BrowserWindow } = require('electron');//导入Electron模块

// 函数index.html页面加载到新的 BrowserWindow 实例中
const createWindow = () => {
  const win = new BrowserWindow({width: 800,height: 600});//设置BrowserWindow 窗口的宽高
  win.loadFile('index.html'); 
}

// 应用准备就绪时调用函数
app.whenReady().then(() => {createWindow()})
// app.on('ready', () => {createWindow()}) 不建议这么调用

// 退出应用程序,不兼容macOS
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {app.quit()}
})

运行npm start ,会打开一个浏览器窗口
在这里插入图片描述

定义全局对象

1.根目录新加新建一个 preload.js,并添加如下代码

const { contextBridge } = require('electron')

// 设置全局变量versions
contextBridge.exposeInMainWorld('versions', {
  // 使用功函数的形式,
  node: () => process.versions.node, // 调用:versions.node()
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron
  // 除函数之外,我们也可以暴露变量
  isBool:true
})

2.将preload.js的代码渲染到进程上,main.js文件中添加如下代码

const path = require('path')

// new BrowserWindow中添加如下代码
webPreferences: {
  preload: path.join(__dirname, 'preload.js')
}

3.根目录新加新建一个 renderer.js,并添加如下代码

const el= document.getElementById('info')
// 调用versions下的方法
el.innerText = ` Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), 和 Electron (v${versions.electron()})`
console.log(versions.isBool) // true
/*
注意: Electron 12 以来,默认情况下已启用上下文隔离,
所以在preload.js中设置window.myAPI全局变量的话,在 renderer.js里面window.myAPI为undefined
window.myAPI = {
  desktop: true
}
*/

4.将renderer.js引入到index.html,并添加一个id为info的标签

<div id="info"></div>
<script src="./renderer.js"></script>

运行 npm start
在这里插入图片描述

进程之间通信

使用 Electron 的 ipcMain 模块和 ipcRenderer 模块来进行进程间通信

渲染器进程到主进程(单向)

将单向 IPC 消息从渲染器进程发送到主进程,使用 ipcRenderer.send API 发送消息,然后使用 ipcMain.on API 接收。
1.main.js添加如下代码

app.whenReady().then(() => {
	...
	// 使用ipcMain.on侦听事件监听set-title
	ipcMain.on('set-title', (event, title) => {
	   const webContents = event.sender
	   const w = BrowserWindow.fromWebContents(webContents)
	   w.setTitle(title)
	 });
 })

2.preload.js添加如下代码

// 将消息发送到上面的ipcMain.on监听器,使用 ipcRenderer.send API
contextBridge.exposeInMainWorld('versions', {
  ...
  setTitle: (title) => ipcRenderer.send('set-title',title),
})

3.触发(调用)versions.setTitle,

// index.html里面新增代码
<input id="btn" type="button" value="渲染器进程到主进程(单向)-设置标题"/>

// renderer.js里面新增代码
const buttonel = document.getElementById('btn')
buttonel.addEventListener('click', () => {
  const title = buttonel.value
  versions.setTitle(title)
})

运行npm run start
在这里插入图片描述

渲染器进程到主进程(双向)

双向 IPC 的一个常见应用是从渲染器进程代码调用主进程模块并等待结果。
通过将 ipcRenderer.invokeipcMain.handle 搭配使用来完成

步骤:
1.网页向主进程发送消息,使用 ipcMain.handle 设置一个主进程处理程序
2.然后在预处理脚本中暴露一个 ipcRenderer.invoke 的函数来触发该处理程序
演示代码如下
1.在main.js中添加如下代码

const { ipcMain } = require('electron')
app.whenReady().then(() => {
	// 设置一个主进程处理程序发送器,监听myfn12
  ipcMain.handle('myfn12', (event,arg) => {
    return '我是myfn的返回:'+ arg;
  });
 ...
})

2.preload.js添加如下代码

contextBridge.exposeInMainWorld('versions', {
  ...,
  electron: () => process.versions.electron,
  myfn: (arg) => ipcRenderer.invoke('myfn12',arg)
})

3.renderer.js新增里面添加如下代码

const fn = async () => {
  const response = await versions.myfn('我传一个参数个myfn');// 传参,接收返回的参数
  information.innerHTML = `${response}`
}
fn()

运行npm start如下图
在这里插入图片描述

主进程到渲染器进程

将消息从主进程发送到渲染器进程时,需要指定是哪一个渲染器接收消息。 消息需要通过其 WebContents 实例发送到渲染器进程。 此 WebContents 实例包含一个 send 方法,其使用方式与 ipcRenderer.send 相同

我们实现如下功能,切换菜单触发
main.js新增如下代码

const { Menu   } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({...})
// ++利用Menu 模块 构建一个菜单
  const menu = Menu.buildFromTemplate([
    {
      label: app.name, // 主菜单使用当前应用的名字
      submenu: [
        {
          click: () => win.webContents.send('update-counter', 1), // 点击子菜单的事件,通过 update-counter 通道向渲染器进程发送消息1
          label: 'Increment' // 子菜单的名字
        },
        {
          click: () => win.webContents.send('update-counter', -1),// 点击子菜单的事件
          label: 'Decrement' // 子菜单的名字
        }
      ]
    }

  ])

  Menu.setApplicationMenu(menu)
}


app.whenReady().then(() => {
	...
  // ++监听counter-value
  ipcMain.on('counter-value', (_event, value) => {
    console.log('avlue'+value) // will print value to Node console
  })
})

preload.js新增如下代码

contextBridge.exposeInMainWorld('versions', {
  ...
  handleCounter: (callback) => ipcRenderer.on('update-counter', callback), // 再此处监听update-counter
})

renderer.js新增如下代码

const counter = document.getElementById('counter')
/*
调用handleCounter后,会开始监听"update-counter"(监听的代码在preload.js中),
点击菜单的时候会发送数据到update-counter触发,进入到下面的回调中,进入回调后,向counter-value发送了数据,
在main.js中counter-value中可以监听到数据,
*/ 
window.versions.handleCounter((event, value) => {
  const oldValue = Number(counter.innerText)
  const newValue = oldValue + value
  counter.innerText = newValue
  event.sender.send('counter-value', newValue); // 在此处send
})

index.html新增如下代码

 当前值: <strong id="counter">0</strong>

运行npm start 效果如下
在这里插入图片描述

打开调试器

// 打开 DevTools.
 win.webContents.openDevTools()

运行npm start如下,打开了谷歌的调试器
在这里插入图片描述

打包应用程序

将 Electron Forge 的 CLI 工具包安装到项目的 devDependencies 依赖中,然后使用现成的转化脚本将项目导入至 Electron Forge。
Electron Forge CLI 文档。
1.根目录运行以下命令,安装依赖

npm install --save-dev @electron-forge/cli
npx electron-forge import

安装完后会发现,package.json中多了一些代码,以及多了一个 forge.config.js文件
在这里插入图片描述

2,。运行以下命令

npm run make

如果出现以下报错,记得填写package.json中的description和author
在这里插入图片描述

打包完成后,根目录会出现一个 out 文件夹,其中包括可分发文件与一个包含其源码的文件夹

out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app

out/make 文件夹中的应用程序(.exe),双击exe文件就可以启动了
在这里插入图片描述

对代码进行签名

代码签名是交付桌面应用程序的重要组成部分,并且它对于应用程序的自动更新功能 (将会在教程最后部分讲解) 来说是必需的

为了将桌面应用程序分发给最终用户,建议应用进行代码签名。

在 macOS 上,代码签名是在应用程序打包时完成的。 而在 Windows 中,则是对可分发文件进行签名操

如果您已经拥有适用于 Windows 和 macOS 的代码签名证书,可以在 Forge 配置中设置您的凭据
签署 macOS 应用程序 指南

macOS端
forge.config.js文件

module.exports = {
  packagerConfig: {
    osxSign: {},
    // ...
    osxNotarize: {
      tool: 'notarytool',
      appleId: process.env.APPLE_ID,
      appleIdPassword: process.env.APPLE_PASSWORD,
      teamId: process.env.APPLE_TEAM_ID
    }
    // ...
  }
}

Windows端
forge.config.js文件

module.exports = {
  // ...
  makers: [
    {
      name: '@electron-forge/maker-squirrel',
      config: {
        certificateFile: './cert.pfx',
        certificatePassword: process.env.CERTIFICATE_PASSWORD
      }
    }
  ]
  // ...
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决构建maven工程时,配置了阿里云的前提下,依旧使用中央仓库下载依赖导致失败的问题!!!

问题描述&#xff1a; 在使用spring进行构建项目时&#xff0c;出现下载依赖迟迟不成功&#xff0c;显示maven wrapper 下载失败的问题。 Maven wrapper Cannot download ZIP distribution from https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/ap…

[模版总结] - 集合划分类DFS模版

题目描述 给定一个数组&#xff0c;给定一个数字k, 问能不能讲数组内数等分成k份&#xff0c;使得每一个集合中数和相等。 题目链接 下面两道题问题及其类似&#xff0c;可作为同一类题目思考 Leetcode 698 Leetcode 473 题目思路 这道题是一道经典集合划分类问题&#…

python pygbag教程 —— 在网页上运行pygame程序(全网中文教程首发)

pygame是一款流行的游戏制作模块&#xff0c;经过特殊的方式编译后&#xff0c;可以在浏览器web网页上运行。web上的打包主要使用第三方模块pygbag。 pygame教程&#xff1a;Python pygame(GUI编程)模块最完整教程&#xff08;1&#xff09;_pygame模块详解_Python-ZZY的博客-…

Day.4 刷题练习(自守数)

题目&#xff1a; 例子&#xff1a; 分析题目&#xff1a; 主要目的&#xff1a;给定一个范围小于等于N&#xff0c;在这个范围中找自守数&#xff08;自身等于平方后的尾部数据如5&#xff1a;5 ^ 2 25 &#xff0c; 然后 5 与 平方的后的尾部相等&#xff09; 思路&#x…

Windows安装PyTorch

文章目录 前言CPU版本安装安装步骤测试CPU版PyTorch是否安装成功 GPU版本安装新建一个conda环境安装torch法一&#xff1a;在线安装(建议用法二)法二&#xff1a;下载torch、torchvision后本地安装(建议使用此方法)Jupyter Lab虚拟环境的配置测试是否安装成功 前言 此份文档适…

2023 蓝桥杯真题B组 C/C++

https://www.dotcpp.com/oj/train/1089/ 题目 3150: 蓝桥杯2023年第十四届省赛真题-冶炼金属 题目描述 小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V&#xff0c;V 是一个正整数&#xff0c;这意味着消耗 V 个普通金 属 O…

【计算机网络】传输层协议 -- UDP协议

文章目录 1. 传输层相关知识1.1 端口号1.2 端口号范围划分1.3 知名端口号1.4 一些相关命令 2. UDP协议2.1 UDP协议格式2.2 UDP协议的特点2.3 什么是面向数据报2.4 UDP的缓冲区2.5 UDP使用注意事项2.6 基于UDP的应用层协议 1. 传输层相关知识 传输层是计算机网络中的一个重要层…

Spring Boot与MyBatis结合实现mock平台

上一章&#xff1a; 测开工具&#xff1a;spring boot 实现mock平台_springboot搭建mock_做测试的喵酱的博客-CSDN博客 代码地址&#xff1a; GitHub - 18713341733/mock: Spring Boot与MyBatis结合 实现对mock平台改造 一、背景 读取数据改为从mysql数据库中读取。 Sp…

redis群集(主从复制)

---------------------- Redis 主从复制 ---------------------------------------- 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(Master)&#xff0c;后者称为从节点(Slave)&#xff1b;数据的复制是单向的&#xf…

QT基于TCP协议实现数据传输以及波形绘制——安卓APP及Windows程序双版本

文章代码有非常非常之详细的解析&#xff01;&#xff01;&#xff01;诸位可放心食用 这个玩意我做了两个&#xff0c;一个是安卓app&#xff0c;一个是Windows程序。代码并非全部都是由我从无到有实现&#xff0c;只是实现了我想要的功能。多亏了巨人的肩膀&#xff0c;开源…

农业中的计算机视觉 2023

物体检测应用于检测田间收割机和果园苹果 一、说明 欢迎来到Voxel51的计算机视觉行业聚焦博客系列的第一期。每个月&#xff0c;我们都将重点介绍不同行业&#xff08;从建筑到气候技术&#xff0c;从零售到机器人等&#xff09;如何使用计算机视觉、机器学习和人工智能来推动…

【导入外部jar包到maven项目中--亲测可行】

若项目为springweb项目&#xff0c;则先将jar放到WEB-INF/lib 目录下选中对应的jar包&#xff0c;右键选项 add-lirrary &#xff1b;成功加入之后的jar包是一个项目的目录结构&#xff1a; 至此&#xff0c;项目能够正常运行&#xff0c;在代码周也能够进行导包 转折点&…

Vue2 第二节 ----初识Vue(简单示例,模板语法,数据绑定)

知识点&#xff1a; 1.Vue的简单示例 2.模板语法 3.数据绑定 4.el和data的两种写法 5.MVVM模型 一. Vue的简单实例 <div id"root"><h1>hello, {{name.toUpperCase()}}, {{address}}</h1></div><script type"text/javascript&q…

2023年二季度中国手机销量排行榜:华为逆袭上榜,苹果仅位列第五,第一名很意外!

近日&#xff0c;国际数据公司&#xff08;IDC&#xff09;现发布最新手机季度跟踪报告显示&#xff0c;2023 年第二季度&#xff0c;中国智能手机市场出货量约 6,570 万台&#xff0c;同比下降 2.1%&#xff0c;降幅明显收窄。 今年上半年&#xff0c;中国智能手机市场出货量…

了解Unity编辑器之组件篇Physics 2D(十二)

一、Area Effector 2D区域施加力&#xff09;&#xff1a;用于控制区域施加力的行为 Use Collider Mask&#xff08;使用碰撞器遮罩&#xff09;&#xff1a;启用后&#xff0c;区域施加力仅会作用于特定的碰撞器。可以使用Collider Mask属性选择要作用的碰撞器。 Collider Ma…

揭秘低代码谜团,好用到不行

一、前言 低代码“灵活、快速、低门槛”的标签&#xff0c;为其带来了诸多争议。在低代码平台上是否只能搭建极其简单、无亮点的小功能&#xff1f;低代码带来的“全民程序员”化是否能真正带来社会价值&#xff1f;这是一场繁荣的泡沫假象&#xff0c;还是真实的市场需求&…

浅谈深拷贝与浅拷贝

一、拷贝&#xff08;克隆&#xff09;的意义的场景 意义&#xff1a;保证原数据的完整性和独立性 常见场景&#xff1a;复制数据、函数入参、class构造函数 二、浅拷贝 只克隆对象的第一层级如果属性值是原始数据类型&#xff0c;拷贝其值&#xff0c;即&#xff1a;值拷贝…

anaconda切换python版本

1 查看环境 conda env list结果如下图&#xff0c;左侧表示已下载的环境信息&#xff0c;当前我已经下载了python3.10&#xff08;python310&#xff09;和3.9&#xff08;python39&#xff09;两个版本 2 切换python版本 conda activate python3103 下载python # 下载pyt…