Electron+Vue3+Vite的产品级模板项目

1. electron-vue3-template

基于Vue3 + Electron + TypeScript的客户端程序模板,使用ViteElectron Forge构建和打包。

真正做到开箱即用,面向跨平台客户端设计,产品级的项目模板。

项目地址:
https://github.com/winsoft666/electron-vue3-template

请添加图片描述

1.1 特性

  • 使用ViteJS构建和驱动前端页面,支持热加载(HMR),使开发和调试变得更加高效 ⚡
  • 支持Vue3多页面,提供页面创建指令,适合客户端开发场景 💖
  • 支持Electron窗口创建指令,并且可隔离不同窗口的IPC事件 💖
  • 封装简化了IPC的调用方式,并提供了IPC函数快速创建指令,主进程与渲染进程的相互调用从未如此简单 👍
  • 主进程和渲染进程支持热加载 ⚡
  • 精选依赖包,提升项目稳定性
  • 代码简洁,易掌控,可定制性强
  • 日志文件,主进程和渲染进程可以直接写文件日志
  • 配置文件
  • 文件下载(含哈希校验、进度反馈),渲染进程可直接异步调用 👍
  • 功能完善的无边框窗口
  • 托盘图标和右键菜单,窗口关闭时程序最小化到托盘
  • 客户端程序单实例
  • 基于ESLint的代码规范和自动格式化
  • 使用Electron官方推荐的Electron Forge进行客户端构建和打包
  • 支持NSIS安装包 😎

1.2 快速开始 🌈

点击右上角绿色的 Use this template 按钮,使用该模板创建一个新的仓库并克隆到本地。

或者…

直接克隆该项目: git clone https://github.com/winsoft666/electron-vue3-template.git

Visual Studio Code

推荐使用Visual Studio Code进行项目开发,并安装如下插件:

  • ESLint
  • Vue Language Features (Volar)

安装依赖 ⏬

yarn install

开发 ⚒️

yarn run dev

其他命令

yarn run dev # 启动应用并支持热加载
yarn run build # 构建应用,可发布的包位于"out\make"目录# 或者
yarn run build:win32 # 构建Windows平台 32位应用
yarn run build:win64 # 构建Windows平台 64位应用
yarn run build:mac # 构建macOS平台应用
yarn run build:linux # 构建Linux平台应用yarn run new:page  # 创建新的Vue页面
yarn run new:window # 创建新的Electron窗口

更多的可选配置项可以参考 Electron Forge CLI docs。

NSIS安装包 🪟

需要先手动下载和安装NSIS:
https://nsis.sourceforge.io/Download

使用如下命令构建Windows平台 32位应用(如需构建64位应用,则需要手动修改win-setup-x86.nsi脚本):

yarn run build:win32

运行NSIS安装目录内的makensisw.exe

依次点击File -> Load Script...,选择并加载本项目的setup\NSIS\win-setup-x86.nsi脚本。

最后,执行Recompile命令即可编译生成安装包。

请添加图片描述

2. 项目介绍

2.1 工程结构 🌳

- scripts/         # 该目录中的脚本用构建应用程序和驱动前端页面
- screenshots      # 本文档中用到的截图
- setup/            # 存储编译和构建相关文件- NSIS/                # NSIS安装包脚本- exe.ico             # 构建后的可执行文件图标(非安装包图标)- install.ico        # NSIS安装包图标- uninstall.ico      # NSIS卸载程序图标
- src/- lib/            # 公共库,为了方便修改,未做成独立的包- file-download/    # 文件下载库- main                 # 仅供主进程使用- renderer            # 仅供渲染进程使用- shared               # 主进程和渲染进程都可以使用- utils/            # 公共代码库- main/           # 主进程的代码 (Electron)- static/          # 静态资源- windows/         # 多窗口文件夹 (每个子目录表示一个窗口)- primary/          # 主窗口(客户端通常都会有一个主窗口)- frameless/        # 无边框示例窗口- ...- renderer/      # 渲染进程的代码 (VueJS)- public           # 静态资源- pages/           # 多页面目录 (强制约定:每个子目录代表一个页面)- primary/          # 主窗口页面- frameless/        # 无边框示例窗口的页面- ...- typings/         # ts声明文件

2.2 使用静态文件

  • src/main/static目录存放主进程使用的静态文件。
  • src/renderer/public目录存放渲染进程使用的静态文件。
在主进程中引用静态文件
// 假设 src/main/static/tray.ico 文件存在
// 使用 appState.mainStaticPath 属性获取主进程的静态文件存储目录
import path from "path";
import appState from "./app-state";const iconPath = path.join(appState.mainStaticPath, "tray.ico");

2.3 AppState对象

为了方便在主进程中跨模块访问某些对象(如primaryWindowtraycfgStore等)和应用配置(如onlyAllowSingleInstance等),我们定义了单实例对象AppState来存储这些数据。

使用方法如下:

import appState from "./app-state";appState.primaryWindow?.show();

2.4 快速创建Vue页面

执行如下命令,输入页面名称后将自动在renderer/pages目录创建子页面,每个子页面的相关代码位于单独的目录中,目录名为我们指定的页面名称(小写)。

yarn run new:page

创建的子页面在代码中通过以下方式访问:

// 开发环境
const rendererPort = process.argv[2];
primaryWindow.loadURL(`http://localhost:${rendererPort}/pages/<PAGE-NAME>/index.html`);// 非开发环境
primaryWindow.loadFile(path.join(app.getAppPath(), "build/renderer/pages/<PAGE-NAME>/index.html"));

2.5 快速创建Electron窗口

虽然直接构造Electron的BrowerWindow对象就可以创建新的Electron窗口,但为了方便代码管理和ipcMain消息隔离,本模板中的每个窗口都继承自WindowBase对象,每个窗口的相关代码位于src\main\windows\的不同子目录中,目录名为我们指定的窗口名称(小写)。

yarn run new:window

创建的子窗口默认会访问同名的子页面,可以手动修改代码访问其他页面:

if(process.env.NODE_ENV === "development"){const rendererPort = process.argv[2];primaryWindow.loadURL(`http://localhost:${rendererPort}/pages/primary/index.html`);
}else{primaryWindow.loadFile(path.join(app.getAppPath(), "build/renderer/pages/primary/index.html"));
}

创建窗口后,需要在registerIpcMainHandler方法中注册该窗口的ipcMain事件及处理函数。

如果多个窗口注册了同名的事件,当渲染进程发送该名称的事件到主进程时,所有窗口对象都会收到该事件,为了避免这种情况,我们可以在事件处理函数中使用isIpcMainEventBelongMe方法来过滤非本窗口的事件。

ipcMain.on("message", (event, message) => {if(!this.isIpcMainEventBelongMe(event))return;console.log(message);
});

2.6 快速创建IPC函数

src\renderer\pages\primary\App.vue中获取文件MD5的代码如下:

async function onGetFileMd5(){const result = await utils.showOpenDialog({properties: [ "openFile" ],filters: [{ name: "All Files", extensions: [ "*" ] }]});if(result.filePaths.length > 0){utils.getFileMd5(result.filePaths[0]).then((md5) => {message.success(md5);}).catch((e) => {message.error(GetErrorMessage(e));});}
}

上述代码通过调用Utils库的showOpenDialoggetFileMd5函数轻松实现了通知主进程选择文件、计算文件MD5并获取相应结果的操作,代码非常简洁。

但是Utils只预置了部分常用的功能,预置功能肯定无法满足我们产品开发的所有需求。在此情况下,我们可以向Utils库中添加自定义的功能函数,该如何添加了?

不用担心,本模板已经提供了IPC函数快速创建指令:

yarn run new:ipc

执行上面指令后,会出现如下提示:

Create syntax: CallWay,FunctionName,FunctionType
Call Way:rm = Renderer process call the function of main processmr = Main process call the function of renderer process (Ignore FunctionType)
Function Name:xxx-xxx-xxx
Function Type:a = Asynchronous call without resultap = Asynchronous call with promise results = Synchronous call with result

参数1(CallWay)表示函数调用方向:

  • rm 表示渲染进程调用主进程的函数,可以支持同步调用、异步调用,并且可以返回Promise结果。
  • mr 表示主进程调用渲染进程的函数,该方向只能是异步调用,而且不支持返回结果,会忽略第三个参数(FunctionType)。

参数2(FunctionName)表示函数名称,函数名称的单词间使用-分隔,如GetFileSha256需要指定为get-file-sha256

参数3(FunctionType)函数类型:

  • a 表示不返回结果的异步函数
  • ap 表示返回Promise结果的异步函数
  • s 表示同步函数

示例

依次输入如下命令:

yarn run new:ipcInput:
rm,get-file-sha256,ap

命令执行成功后,会自动在src\lib\utils\renderer\index.ts生成Utils.getFileSha256函数:

public async getFileSha256(){return await (window as any).__ElectronUtils__.getFileSha256();
}

自动生成的函数都没有指定参数和返回值,需要我们手动添加,如修改后的函数如下:

public async getFileSha256(filePath: string) : string {return await (window as any).__ElectronUtils__.getFileSha256(filePath) as string;
}

在渲染进程中(如App.vue)中可以直接调用该函数:

import utils from "../../../lib/utils/renderer";const sha256 = await utils.getFileSha256("file-path.txt");

IPC函数创建指令只会创建函数骨架,不会为我们实现具体的功能,我们还需要在主进程ipcMain处理函数中实现计算文件SHA256的具体功能。

自动生成的主进程ipcMain处理函数如下:

ipcMain.handle("electron-utils-get-file-sha256", async(event) => {
});

手动添加参数、返回值,及具体的功能代码(此处省略):

ipcMain.handle("electron-utils-get-file-sha256", async(event, filePath: string) : Promise<string> => {// .....
});

3. 代码规范

本项目使用ESLint进行代码检查和格式化,没有使用Prettier进行代码格式化。

原因大体如下:

  1. 需要额外的插件和配置来避免ESLint和Prettier的规则冲突。

  2. Prettier的printWidth配置项会损害代码和Git Diff的可读性。
    请添加图片描述
    请添加图片描述

在线演示

4. 依赖包 🎈

4.1 基本原则

一个构建在众多不稳定性因素下的项目,是没有稳定性可言的。

为了保证项目的稳定性,本模板项目只使用具有知名度、稳定性强的依赖包(库),如electron-log等。

对于作者自己写的库(如file-download等),统一以源码形式提供在src\lib\目录,方便模板使用者进行bug修复和功能扩充,在使用时直接采用相对路径进行导入即可。

4.2 dependencies和devDependencies的区别

由于Electron Forge会将dependencies中的所有依赖项都进行打包,因此为了减少安装包的体积,我们只将主进程需要使用的依赖安装到dependencies项下,而其他的依赖均安装到devDependencies

如将vue作为开发依赖进行安装:

yarn add -D vue

4.3 依赖包说明

作为开发者,应知晓每个依赖包的用途,避免node_modules黑洞的产生。

  • unplugin-vue-components
    实现自动按需引入AntDesign-Vue组件。

  • electron-log
    提供本地日志文件的打印和输出。

  • electron-store
    提供本地配置文件的读取和写入功能。

  • @fortawesome-*
    提供对FontAwesome图标字体的支持。

  • uuid
    使用uuid字符串,在file-download库中使用。

  • chalk
    用于在命令行终端输出带颜色样式的字符串,仅在scripts\*.js中使用。

  • chokidar
    轻量级的文件监控组件,用于实现热加载,仅在scripts\*.js中使用。

  • @electron-forge/*
    与Electron Forge构建和打包相关的依赖包,除了@electron-forge/cli是必须的,其他的可以根据forge.config.js -> makers的配置按需引用。

5. 客户端版本号

使用package.json文件的version字段标识客户端的版本号,在主进程内可以通过appState.appVersion属性获取。

💡 不需要设置forge.config.js文件的appVersion字段。

在渲染进程可以直接使用utils.getAppVersion()获取版本号。

import utils from "../../../lib/utils/renderer";console.log(utils.getAppVersion());

6. 期待你的反馈 🥳

个人能力有限,代码不免有错误和不足之处,欢迎提交issue和PR。

如果这个项目对你有帮助,无需捐助,点击右上角Star ⭐让我知道就可以了。

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

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

相关文章

第5课 使用FFmpeg将rtmp流再转推到rtmp服务器

本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88801992 通过前面的学习&#xff0c;我们已经可以正常播放网络rtmp流及本地mp4文件。这节课&#xff0c;我们将在前面的基础上实现一个常用的转推功能&#xff1a;读取rtmp流或mp4文件并…

架构学习(二):原生scrapy如何接入scrapy-redis,初步入局分布式

原生scrapy如何接入scrapy-redis&#xff0c;实现初步入局分布式 前言scrpy-redis分布式碎语 实现流程扩展结束 前言 scrpy-redis分布式 下图是scrpy-redis官方提供的架构图&#xff0c;按我理解&#xff0c;与原生scrapy的差异主要是把名单队列服务器化&#xff0c;也是存储…

Modbus协议学习第七篇之libmodbus库API介绍(modbus_write_bits等)

写在前面 在第六篇中我们介绍了基于libmodbus库的演示代码&#xff0c;那本篇博客就详细介绍一下第六篇的代码中使用的基于该库的API函数。另各位读者&#xff0c;Modbus相关知识受众较少&#xff0c;如果觉得我的专栏文章有帮助&#xff0c;请一定点个赞&#xff0c;在此跪谢&…

自然语言处理(NLP)—— Dialogflow ES聊天机器人

1. 背景介绍 这个实验室的目标是让你了解并使用Google的Dialogflow服务。Dialogflow是一个可以让你创建聊天机器人的服务&#xff0c;这个过程不需要或者只需要很少的编程技能。 1.1 账号的创建 为了完成这个实验室&#xff0c;你需要在以下网站上创建账号&#xff1a…

网络安全之SSL证书加密

简介 SSL证书是一种数字证书&#xff0c;遵守SSL协议&#xff0c;由受信任的数字证书颁发机构&#xff08;CA&#xff09;验证服务器身份后颁发。它具有服务器身份验证和数据传输加密的功能&#xff0c;能够确保数据在传输过程中的安全性和完整性。 具体来说&#xff0c;SSL证…

excel统计分析——卡方独立性检验(下)

参考资料&#xff1a;生物统计学 书接上文&#xff1a;https://blog.csdn.net/maizeman126/article/details/135893731 2、配对列联表 配对设计的数据&#xff0c;进行列联表检验时&#xff0c;采用McNemar-Bowker检验法进行检验。检验统计量为&#xff1a; 自由度dfk(k-1)/2…

Jmeter直连mysql数据库教程

mysql数据库能够通过Navicat等远程连接工具连接 下载驱动并加入jmeter 1.mysql驱动下载地址&#xff1a;MySQL :: Download MySQL Connector/J (Archived Versions) 找到对应的驱动下载&#xff1a;如下图&#xff1a; 把驱动jar包加入jmeter 配置jmeter连接mysql数据库…

计算机专业一定要参加蓝桥杯吗

蓝桥杯对于计算机专业的学生来说是一个非常重要的赛事&#xff0c;主要有以下几个原因&#xff1a; 提升知识和技能水平&#xff1a;蓝桥杯涵盖了计算机专业的多个方向&#xff0c;包括软件、硬件、网络等。通过参加蓝桥杯&#xff0c;学生可以将所学的知识与实际应用相结合&a…

RK3588 Android 12 Framework修改记录(八)Settings Ethernet以太网 多网卡设置静态IP

https://blog.csdn.net/lishu_/article/details/114391764 如何优雅的实现Android Ethernet 以太网的开启与关闭 RK3588 Android 12 Framework修改记录&#xff08;八&#xff09;Settings Ethernet以太网 多网卡设置静态IP - 知乎 Android 7.1 以太网反射 EthernetManager 配置…

【C语言刷题系列】喝汽水问题

文章目录 一、文章简介 1.先买再换 1.1 代码逻辑&#xff1a; 1.2 完整代码 1.3 运行结果 1.4 根据方法一总结优化 2.边买边换 2.1 代码逻辑&#xff1a; 2.2 完整代码 2.3 运行结果 一、文章简介 本文所述专栏——C语言经典编程问题 C语言刷题_倔强的石头106的博客…

Linux操作系统——管道(二) 进程池

概念层面理解进程池 比如说我们一开始有一个父进程&#xff0c;分别创建5个管道&#xff0c;5个子进程&#xff0c;这5个子进程都向管道里面进行读取&#xff0c;而我们对应的父进程&#xff0c;因为我们前面谈过管道的4种情况里面&#xff0c;有一个种情况是&#xff0c;正常…

vcruntime140.dll怎么下载安装,vcruntime140.dll详细安装教程

vcruntime140.dll’&#xff0c;这个看似陌生而又技术性的文件名&#xff0c;实际上是计算机系统中一个至关重要的动态链接库文件。它是Visual C Redistributable运行时组件的一部分&#xff0c;由微软公司开发并维护&#xff0c;对于许多基于Windows操作系统的软件正常运行起着…

PEI是聚醚酰亚胺(Polyetherimide)在粘接使用时使用UV胶水的优势有哪些?要注意哪些事项?

在使用UV胶水进行聚醚酰亚胺&#xff08;Polyetherimide&#xff0c;PEI&#xff09;粘接时&#xff0c;有一些优势和注意事项&#xff1a; 优势&#xff1a; 1.快速固化&#xff1a; UV胶水具有快速固化的特性&#xff0c;通过紫外线光源的照射&#xff0c;可以在几秒到几分钟…

国标GB/T 28181详解:GB/T28181状态信息报送流程

目 录 一、状态信息报送 二、状态信息报送的基本要求 三、命令流程 1、流程图 2、流程描述 四、协议接口 五、产品说明 六、状态信息报送的作用 七、参考 在国标GBT28181中&#xff0c;定义了状态信息报送的流程&#xff0c;当源设备(包括网关、SIP 设备、SIP 客…

关于可变类型和不可变类型的探究

个人猜想&#xff08;很遗憾失败了&#xff09; 在硬盘或者系统中存在一个字符集 如果存在硬盘中&#xff0c;那么硬盘出厂的时候他的字符集所占用的空间就已经确定了。 如果存在于系统的话&#xff0c;硬盘应该在出厂的时候为系统设置一个存储系统字符集的地方。在安装系统…

数据库建模之PowerDesigner创建概念模型

数据模型&#xff08;Data Model&#xff09;是数据特征的抽象&#xff0c;它从抽象层次上描述了系统的静态特征、动态行为和约束条件&#xff0c;为数据库系统的信息表示与操作提供一个抽象的框架。数据模型所描述的内容有三部分&#xff0c;分别是数据结构、数据操作和数据约…

模拟请求ElasticSearch

Step1 安装chrome的这个插件 Step2 打开插件&#xff0c;GET的json填什么。 在IDEA的debug模式&#xff0c;走到Java代码的searchBuilder&#xff0c; 在这个searchBuilder变量里&#xff0c;对里面query变量点右侧 view按钮&#xff0c; IDEA里会显示出一个json&#xff…

Redis核心技术与实战【学习笔记】 - 16.Redis 缓存异常:缓存和数据库不一致

概述 只要使用 Redis 缓存&#xff0c;就必须面对缓存和数据库的一致性问题。 重要的是&#xff0c;如果数据不一致&#xff0c;那么业务应用从缓存中读取的数据就不是最新数据&#xff0c;这会导致严重的问题。比如说&#xff0c;我们把电商商品的库存信息缓存在 Redis 中&am…

Datax问题记录

1、同步mysql&#xff1a;OS errno 24 - Too many open files 2023-11-20 12:30:04.371 [job-0] ERROR JobContainer - Exception when job run com.alibaba.datax.common.exception.DataXException: Code:[DBUtilErrorCode-07], Description:[读取数据库数据失败. 请检查您的…

1.27马尔科夫链,抽样蒙特卡洛模拟(逆转化方法,接受拒绝矩阵),马尔科夫链蒙特卡洛MCMC,隐马尔科夫(HMM(V算法剪枝优化),NLP)

马尔科夫链 蒙特卡洛法模拟 抽样&#xff0c;逆转换方法 就是说由系统自带的随机函数RANDOM&#xff0c;通过下面这个方法&#xff0c;可以变为对应的随机模拟函数 就是说要实现蒙特卡洛模拟&#xff0c;是要先有一个概率表达式&#xff0c;然后基于这个概率表达式&#xff0…