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

electron 网页TodoList应用打包win桌面软件数据持久化

参考:
electron 网页TodoList工具打包成win桌面应用exe
https://blog.csdn.net/weixin_42357472/article/details/140648621

electron直接打包exe应用,打开网页上面添加的task在重启后为空,历史没有被保存,需要持久化工具保存之前的操作记录

这里测试用electron-store或electron-conf两个持久化工具运行都ESM报错:
https://zhuanlan.zhihu.com/p/706281785
在这里插入图片描述

解决方法:
直接使用 Node.js 的 fs 模块直接读写 JSON 文件。这样可以避免 ES modules 的问题。
1)electron配置文件
main.js

const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const fs = require('fs')const STORAGE_PATH = path.join(app.getPath('userData'), 'todos.json')function saveTodos(todos) {fs.writeFileSync(STORAGE_PATH, JSON.stringify(todos))
}function loadTodos() {try {return JSON.parse(fs.readFileSync(STORAGE_PATH, 'utf8'))} catch (error) {return []}
}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()}
})// 修改这些 IPC 处理器
ipcMain.on('save-todos', (event, todos) => {saveTodos(todos)
})ipcMain.handle('load-todos', () => {return loadTodos()
})

package.json

{"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"},"dependencies": {}
}

2)网页应用
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 { ipcRenderer } = require('electron')const todoForm = document.getElementById('todo-form')
const todoInput = document.getElementById('todo-input')
const todoList = document.getElementById('todo-list')async function loadTodos() {const todos = await ipcRenderer.invoke('load-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')}))ipcRenderer.send('save-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() === '') returnaddTodoToDOM(todoInput.value)saveTodos()todoInput.value = ''
})loadTodos()

打包:

npm run build

在这里插入图片描述
完成在dist下生产安装文件,及win-unpacked 无需安装的解压文件
在这里插入图片描述
在这里插入图片描述
点击exe运行即可
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 00-从零开始安装Oracle19c之数据库安装规划
  • 这款ERP云进销存系统,直接封神
  • 【排序】快速排序详解
  • 《学会 SpringMVC 系列 · 基础篇》
  • 华为OD机试 - Wonderland游乐园 - 动态规划(Java 2024 D卷 200分)
  • 遥感领域新方向!Mamba+RS论文汇总!
  • Undertow详解
  • Spring Boot:SpringBoot入门
  • DHCP与DNS的配置
  • 【屏显MCU】多媒体接口总结
  • LNMP动态网站环境部署
  • Javascript中canvas与svg详解
  • LLM评估 | 大模型评估方法调研--论文解读(持续更新ing!!!)
  • iexcel-excel 大文件读取和写入-04-order 指定列顺序
  • Spring源码学习笔记之@Async源码
  • [deviceone开发]-do_Webview的基本示例
  • 10个最佳ES6特性 ES7与ES8的特性
  • Apache Spark Streaming 使用实例
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • input的行数自动增减
  • java第三方包学习之lombok
  • JS变量作用域
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • php ci框架整合银盛支付
  • 初识 webpack
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 每天一个设计模式之命令模式
  • 我看到的前端
  • 我有几个粽子,和一个故事
  • 以太坊客户端Geth命令参数详解
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • Nginx实现动静分离
  • 第二十章:异步和文件I/O.(二十三)
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #pragam once 和 #ifndef 预编译头
  • (+4)2.2UML建模图
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (差分)胡桃爱原石
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)视频码率,帧率和分辨率的联系与区别
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .Net 垃圾回收机制原理(二)
  • .net经典笔试题
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...