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

bash 复制代码
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

bash 复制代码
{
  "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

bash 复制代码
<!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

bash 复制代码
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

bash 复制代码
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() === '') return

    addTodoToDOM(todoInput.value)
    saveTodos()
    todoInput.value = ''
})

loadTodos()

打包:

bash 复制代码
npm run build

完成在dist下生产安装文件,及win-unpacked 无需安装的解压文件

点击exe运行即可

相关推荐
kyriewen16 小时前
别再 console.log 了:5 个 Chrome DevTools 调试技巧,用过就回不去了
前端·javascript·面试
IT_陈寒18 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
To_OC18 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
DigitalOcean19 小时前
Laravel 开发者已在 DigitalOcean 上开通超过 10 万台服务器
前端·laravel
星始流年19 小时前
从 Tool 到 Skill——基于 LangChain 的服务端Skill实现
前端·langchain·agent
李惟19 小时前
开源本地通信库,纯客户端 RPC,像聊天一样通信
前端
YAwu1119 小时前
深入解析 React 炫彩鼠标跟随标题组件:从坐标定位到动画性能
前端·react.js
GuWenyue19 小时前
排序效率低?5分钟吃透快速排序,性能飙升至O(nlogn)
前端·javascript·面试
OpenTiny社区19 小时前
🎨 看完 GenUI SDK 源码我悟了!
前端·vue.js·github
叁两19 小时前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js