You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron待办任务应用如何实现用户数据本地持久化?

Electron待办任务应用数据持久化解决方案

一、先排查localStorage失效的常见原因

如果你的代码里已经用了localStorage但没生效,先检查这几点:

  1. 数据序列化/反序列化是否正确
    • 存数据时必须把对象转成JSON字符串:
      // 正确写法
      localStorage.setItem('tasks', JSON.stringify(tasksArray));
      
    • 读数据时要解析回对象:
      // 正确写法
      const tasks = JSON.parse(localStorage.getItem('tasks') || '[]');
      
  2. 加载时机是否正确
    确保在DOM完全加载后再调用LoadDataFromStorage,比如:
    document.addEventListener('DOMContentLoaded', () => {
      TaskManager.LoadDataFromStorage();
    });
    
  3. 窗口配置是否限制了存储
    检查main.js的窗口参数,不要禁用浏览器存储相关能力,默认配置即可,不需要额外设置。

二、改用electron-store的具体操作

如果localStorage还是不稳定,推荐用electron-store模块(专门为Electron设计的持久化存储方案,比localStorage更可靠,支持更多数据类型)。

1. 安装依赖

在项目根目录执行:

npm install electron-store

2. 主进程(main.js)配置

初始化存储实例,并通过IPC通信暴露给渲染进程(安全写法,不建议直接开启nodeIntegration):

const { app, BrowserWindow, ipcMain } = require('electron');
const Store = require('electron-store');
const path = require('path');

// 初始化存储,默认会存在用户目录的应用配置文件夹里
const store = new Store();

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 用preload脚本暴露API,安全且符合Electron最新规范
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  });

  mainWindow.loadFile('index.html');
}

// IPC通信:获取任务列表
ipcMain.handle('get-tasks', () => {
  return store.get('tasks', []); // 没有数据时返回空数组
});

// IPC通信:保存新任务
ipcMain.handle('save-task', (_, task) => {
  const tasks = store.get('tasks', []);
  tasks.push(task);
  store.set('tasks', tasks);
});

// IPC通信:删除任务
ipcMain.handle('delete-task', (_, taskId) => {
  const tasks = store.get('tasks', []);
  const updatedTasks = tasks.filter(task => task.id !== taskId);
  store.set('tasks', updatedTasks);
});

app.whenReady().then(() => {
  createWindow();
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

3. 编写preload.js脚本

用来安全地向渲染进程暴露主进程的存储API:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronStoreAPI', {
  getTasks: () => ipcRenderer.invoke('get-tasks'),
  saveTask: (task) => ipcRenderer.invoke('save-task', task),
  deleteTask: (taskId) => ipcRenderer.invoke('delete-task', taskId)
});

4. 渲染进程业务代码修改

修改你的TaskManager类,调用暴露的API:

class TaskManager {
  // 添加任务
  static async AddDataToTable(taskData) {
    // 先存到electron-store
    await window.electronStoreAPI.saveTask(taskData);
    // 动态创建DOM元素
    const table = document.getElementById('task-table');
    const row = table.insertRow();
    row.innerHTML = `
      <td>${taskData.title}</td>
      <td>${taskData.description}</td>
      <td><button onclick="TaskManager.DeleteTask('${taskData.id}')">删除</button></td>
    `;
  }

  // 删除任务
  static async DeleteTask(taskId) {
    await window.electronStoreAPI.deleteTask(taskId);
    // 删除对应DOM行
    const targetRow = document.querySelector(`button[onclick*="${taskId}"]`).closest('tr');
    targetRow?.remove();
  }

  // 加载存储的任务
  static async LoadDataFromStorage() {
    const tasks = await window.electronStoreAPI.getTasks();
    const table = document.getElementById('task-table');
    tasks.forEach(task => {
      const row = table.insertRow();
      row.innerHTML = `
        <td>${task.title}</td>
        <td>${task.description}</td>
        <td><button onclick="TaskManager.DeleteTask('${task.id}')">删除</button></td>
      `;
    });
  }
}

// DOM加载完成后初始化任务列表
document.addEventListener('DOMContentLoaded', async () => {
  await TaskManager.LoadDataFromStorage();
});

// 表单提交事件
document.getElementById('task-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const title = document.getElementById('task-title').value;
  const description = document.getElementById('task-description').value;
  // 生成唯一ID
  const taskData = { id: Date.now().toString(), title, description };
  await TaskManager.AddDataToTable(taskData);
  document.getElementById('task-form').reset();
});

内容的提问来源于stack exchange,提问作者MavapeGZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:00:15