electron 网页TodoList工具打包成win桌面应用exe
参考:
electron安装(支持win、mac、linux桌面应用)
https://blog.csdn.net/weixin_42357472/article/details/140643624
TodoList工具
https://blog.csdn.net/weixin_42357472/article/details/140618446
electron打包过程:
要将这个TodoList网页应用转换成Mac、Windows和Linux的桌面应用,你可以使用Electron框架。Electron允许你使用web技术(HTML、CSS和JavaScript)来创建跨平台的桌面应用。以下是将你的TodoList转换为Electron应用的步骤:
-
准备工作:
首先,确保你的系统中安装了Node.js和npm。 -
创建一个新的Electron项目:
创建一个新文件夹,并在其中初始化一个新的Node.js项目:mkdir todolist-app cd todolist-app npm init -y
这里TodoList工具主要是:index.html、styles.css 、script.js
其他是electron打包需要配置文件:main.js 、package.json

-
安装Electron:
cnpm install electron --save-dev -
创建主进程文件:
在项目根目录创建一个名为main.js的文件,内容如下:const { app, BrowserWindow } = require('electron') const path = require('path')function createWindow () {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true,contextIsolation: false}})win.loadFile('index.html') }app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}}) })app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()} }) -
修改package.json:
在package.json文件中添加以下内容:{"main": "main.js","scripts": {"start": "electron ."} } -
将你的HTML、css、js文件放在项目根目录
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>TodoList</title><link rel="stylesheet" href="styles.css">
</head>
<body><h1>TodoList</h1><form id="todo-form"><input type="text" id="todo-input" placeholder="Enter a new task" required><button type="submit" id="add-button">Add</button></form><ul id="todo-list"></ul><script src="script.js"></script>
</body>
</html>
styles.css
body {font-family: Arial, sans-serif;max-width: 500px;margin: 0 auto;padding: 20px;
}
h1 {text-align: center;
}
#todo-form {display: flex;margin-bottom: 20px;
}
#todo-input {flex-grow: 1;padding: 10px;font-size: 16px;border: 1px solid #ddd;border-radius: 4px 0 0 4px;
}
#add-button {padding: 10px 20px;font-size: 16px;background-color: #4CAF50;color: white;border: none;border-radius: 0 4px 4px 0;cursor: pointer;
}
#todo-list {list-style-type: none;padding: 0;
}
.todo-item {display: flex;align-items: center;padding: 10px;background-color: #f9f9f9;border: 1px solid #ddd;margin-bottom: 10px;border-radius: 4px;
}
.todo-item.completed {text-decoration: line-through;opacity: 0.6;
}
.todo-item input[type="checkbox"] {margin-right: 10px;
}
.delete-button {margin-left: auto;background-color: #f44336;color: white;border: none;padding: 5px 10px;border-radius: 4px;cursor: pointer;
}
script.js
const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');function loadTodos() {chrome.storage.sync.get(['todos'], function(result) {const todos = result.todos || [];todos.forEach(todo => {addTodoToDOM(todo.text, todo.completed);});});
}function saveTodos() {const todos = Array.from(todoList.children).map(li => ({text: li.querySelector('span').textContent,completed: li.classList.contains('completed')}));chrome.storage.sync.set({todos: todos});
}function addTodoToDOM(text, completed = false) {const li = document.createElement('li');li.className = 'todo-item' + (completed ? ' completed' : '');li.innerHTML = `<input type="checkbox" ${completed ? 'checked' : ''}><span>${text}</span><button class="delete-button">Delete</button>`;li.querySelector('input[type="checkbox"]').addEventListener('change', function() {li.classList.toggle('completed');if (li.classList.contains('completed')) {todoList.appendChild(li);} else {todoList.insertBefore(li, todoList.firstChild);}saveTodos();});li.querySelector('.delete-button').addEventListener('click', function() {li.remove();saveTodos();});if (completed) {todoList.appendChild(li);} else {todoList.insertBefore(li, todoList.firstChild);}
}todoForm.addEventListener('submit', function(e) {e.preventDefault();if (todoInput.value.trim() === '') return;addTodoToDOM(todoInput.value);saveTodos();todoInput.value = '';
});loadTodos();
-
运行应用:
现在你可以通过以下命令运行你的Electron应用:npm start
看效果

-
打包应用:
要为不同平台打包应用,你可以使用electron-builder。首先安装它:cnpm install electron-builder --save-dev然后在
package.json中添加build配置{"build": {"appId": "com.yourcompany.todolist","mac": {"category": "public.app-category.productivity"},"win": {"target": ["nsis"]},"linux": {"target": ["AppImage","deb"]}},"scripts": {"start": "electron .","build": "electron-builder --mac --win --linux"} }
最终package.json文件:
icon是图标应用,大小至少需要放256*256大小像素的
{"name": "todolist-app","version": "1.0.0","main": "main.js","build": {"appId": "com.yourcompany.todolist","mac": {"category": "public.app-category.productivity"},"win": {"icon": "icons/icon.png","target": ["nsis"]},"linux": {"target": ["AppImage","deb"]}},"scripts": {"start": "electron .","build": "electron-builder --win"},"keywords": [],"author": "","license": "ISC","description": "","devDependencies": {"electron": "^31.2.1","electron-builder": "^24.13.3"}
}
-
构建应用:
运行以下命令来为所有平台构建应用:npm run build这将在
dist文件夹中生成针对Mac、Windows和Linux的安装包。
注意:这里"build": “electron-builder --win” 只生成win平台的,其他linux需wsl打开或者linux平台操作;mac只能mac电脑操作

运行完会再dist文件下

双击exe启动

相关文章:
electron 网页TodoList工具打包成win桌面应用exe
参考: electron安装(支持win、mac、linux桌面应用) https://blog.csdn.net/weixin_42357472/article/details/140643624 TodoList工具 https://blog.csdn.net/weixin_42357472/article/details/140618446 electron打包过程: 要将…...
数据结构之判断二叉树是否为搜索树(C/C++实现)
文章目录 判断二叉树是否为搜索树方法一:递归法方法二:中序遍历法总结 二叉树是一种非常常见的数据结构,它在计算机科学中有着广泛的应用。二叉搜索树(Binary Search Tree,简称BST)是二叉树的一种特殊形式&…...
golang长连接的误用
误用一:忘记读取响应的body 由于忘记读取响应的body导致创建大量处于TIME_WAIT状态的连接(同时产生大量处于transport.go的readLoop和writeLoop的协程) 在linux下运行下面的代码: package mainimport ("fmt""html"&qu…...
Springboot @Validate @Valid 基于复杂嵌套对象的参数校验示例
Springboot Validate Valid 基于复杂嵌套对象的参数校验示例 复杂对象 Data public class Object1 {Length(max 50,message "长度不能超过50位字符")NotBlank(message "名称不能为空")private String name;NotNull(message "不能为空")pri…...
算力共享下的,分级路由转发报文协议与通告
目录 网络双 SLA 约束 一、双SLA约束的定义与背景 二、双SLA约束的应用场景 三、双SLA约束的管理与实施 四、双SLA约束的优势与挑战 算力共享下的,分级路由转发报文协议与通告 基础设施即服务(IaaS)类 型算力资源 函数即服务(FaaS)类型算力服务 软件即服务(SaaS…...
滚动数组详解
滚动数组详解 何为滚动数组?滚动数组是如何优化空间的?交替滚动例题:来自某某轮廓线DP的题目 自我滚动(~~不如交替~~ 完结!!! ( 宇宙免责任书:我用的是C) 何为滚动数组? 什么是滚动…...
C 语言动态链表
线性结构->顺序存储->动态链表 一、理论部分 从起源中理解事物,就是从本质上理解事物。 -杜勒鲁奇 动态链表是通过结点(Node)的集合来非连续地存储数据,结点之间通过指针相互连接。 动态链表本身就是一种动态分配内存的…...
【Leetcode】二十、记忆化搜索:零钱兑换
文章目录 1、记忆化搜索2、leetcode509:斐波那契数列3、leetcode322:零钱兑换 1、记忆化搜索 也叫备忘录,即把已经计算过的结果存下来,下次再遇到,就直接取,不用重新计算。目的是以减少重复计算。 以前面提…...
json数据格式 继续学习
1.定义 轻量级的数据交互格式,可以按照json数据格式去组织和封装数据。 本质是一个带有特定格式的字符串。 2.功能 负责不同编程语言中的数据传递和交互。 3.json数据格式转化 """ 演示json数据和python字典之间的转换 """ impor…...
gradle 构建项目添加版本信息
gradle 构建项目添加版本信息,打包使用 spring boot 的打包插件 build.gradle 配置文件 bootJar {manifest {attributes(Project-Name: project.name,Project-Version: project.version,"project-Vendor": "XXX Corp","Built-By": &…...
vue3 学习笔记17 -- 基于el-menu封装菜单
vue3 学习笔记17 – 基于el-menu封装菜单 前提条件:组件创建完成 配置路由 // src/router/index.ts import { createRouter, createWebHashHistory } from vue-router import type { RouteRecordRaw } from vue-router export const Layout () > import(/lay…...
使用 Redis 实现验证码、token 的存储,用自定义拦截器完成用户认证、并使用双重拦截器解决 token 刷新的问题
可以看一下我以前做过的笔记:黑马点评 短信登录部分 基于session实现登录流程 1.发送验证码 用户在提交手机号后,会校验手机号是否合法,如果不合法,则要求用户重新输入手机号 如果手机号合法,后台此时生成对应的验…...
反转链表 - 力扣(LeetCode)C语言
206. 反转链表 - 力扣(LeetCode)( 点击前面链接即可查看题目) /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head) {if(head NULL)…...
【Linux】进程间通信(1):进程通信概念与匿名管道
人与人之间是如何通信的?举个简单的例子,假如我是月老,我要为素不相识的但又渴望爱情的男女两方牵红线。我需要收集男方的信息告诉女方,收集女方的信息告诉男方,然后由男女双方来决定是否继续。对于他们而言࿰…...
Spring从入门到精通 01
文章目录 1. 依赖注入 (Dependency Injection, DI)2. 面向切面编程 (Aspect-Oriented Programming, AOP)3. 事务管理4. 简化 JDBC 开发5. 集成各种框架和技术6. 模块化和扩展性:主要的 Spring 模块:Core Container:AOP 模块:Data …...
C语言经典习题25
冒泡排序 对一维数组进行升序排序,然后在数组中输入20个数,将排序后的结果打印输出。 #include<stdio.h> #define N 20 int main() {int a[N];int i;for(i0;i<N;i) //初始化数组的数 {scanf("%d",&a);}for(i0;…...
2-47 基于matlab的时域有限差分法(FDTD法)拉夫等效原理进行时谐场外推
基于matlab的时域有限差分法(FDTD法)拉夫等效原理进行时谐场外推。外推边界距离吸收边界的距离、电磁场循环、傅立叶变换提起幅值和相位、各远区剖分点电场、方向系数计算等操作,得出可视化结果。程序已调通,可直接运行。 2-47 时域有限差分法(FDTD法) 拉…...
JupyterNotebook快捷键 自用
COMMAND MODE —————————————————————————————— Up Down cells的上下选择 A B 在上/下方插入cell C V X 复制/粘贴/剪切cell 双击D 删除所选cell Z 恢复被删除的cell 双击I Interrupt中断内核 Shift Enter 运行cell并选择下方 EDIT MODE ———…...
【我的OpenGL学习进阶之旅】讲一讲GL_TEXTURE_2D和GL_TEXTURE_EXTERNAL_OES的区别
在使用OpenGL ES进行图形图像开发时,我们常使用GL_TEXTURE_2D纹理类型,它提供了对标准2D图像的处理能力。这种纹理类型适用于大多数场景,可以用于展示静态贴图、渲染2D图形和进行图像处理等操作。 另外,有时我们需要从Camera或外部视频源读取数据帧并进行处理。这时,我们…...
Makefile 如何将生成的 .o 文件放到指定文件夹
研究了不少文章,我行通了一个,但是也不全,目前只能适用当前文件夹,如果源文件有子文件夹处理不了,还得继续研究。很多人说编译完把O文件移动走或者直接删掉。我想说的是不符合我的要求,移走或者删除O文件&a…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
