electron-vue:项目本地化永久保存数据

前文

        项目需要保存数据,一开始用的 localStorage 做数据缓存,因其缓存容量有限(5M)以及其他原因,需要保存成文件形式。

        我使用node.js的 fs 模块做数据的文件化写入读取以及删除功能。

 

 完整代码

主进程

background.js

const { app, protocol, BrowserWindow, ipcMain  } = require('electron')
const { createProtocol } = require('vue-cli-plugin-electron-builder/lib')

const fs = require('fs');
const path = require('path');

// 指定目录(客户端根目录)
let specifiedDirectory = '';
if(process.platform=='win32'){//Windows
  specifiedDirectory = 'D:\\myProject\\allData\\';
}else{//linux('linux'),macOS('darwin')
  specifiedDirectory = '/home/myProject/allData/';
}

// 确保目录存在
if (!fs.existsSync(specifiedDirectory)) {
  fs.mkdirSync(specifiedDirectory, { recursive: true });// 使用recursive选项可以创建嵌套目录
}

// 写入数据文件
ipcMain.handle('write-file', async (event, options) => {
  try {
    // options 应该包含 data 和文件名
    const { data, filename } = options;
    const filePath = path.join(specifiedDirectory, filename);

    return new Promise((resolve, reject) => {
      fs.writeFile(filePath, JSON.stringify(data), function(err){
        if(err) return reject({ok: false, msg: err.message});
        resolve({ok: true, msg: "写入成功"});
      })
    })
  } catch (error) {
    console.error('background.js写入数据文件时出错:', error);
    return Promise.reject({ok: false, msg: error.message});
  }
})

// 读取数据文件
ipcMain.handle('read-file', async (event, filename) => {
  try {
    const filePath = path.join(specifiedDirectory, filename);

    return new Promise((resolve, reject) => {
      if (fs.existsSync(filePath)) {
        fs.readFile(filePath, "utf8", function(err, dataStr){
          if(err) return reject({ok: false, msg: err.message});
          resolve({ok: true, msg: JSON.parse(dataStr)});
        })
      } else {
        resolve({ok: false, msg: "无对应文件"});
      }
    })
  } catch (error) {
    console.error('background.js读取数据文件时出错:', error);
    return Promise.reject({ok: false, msg: error.message});
  }
})

// 删除数据文件
ipcMain.handle('remove-file', async (event, filename) => {
  try {
    const filePath = path.join(specifiedDirectory, filename);

    return new Promise((resolve, reject) => {
      if (fs.existsSync(filePath)) {
        fs.unlink(filePath, function (err) {
          if(err) return reject({ok: false, msg: err.message});
          resolve({ok: true, msg: "删除成功"});
        })
      } else {
        resolve({ok: false, msg: "无对应文件"});
      }
    })
  } catch (error) {
    console.error('background.js删除数据文件时出错:', error);
    return Promise.reject(false, error.message);
  }
})


async function createWindow() {
  const win = new BrowserWindow({
    width: 1280,
    height: 800,
    frame: isDevelopment, // 无边框窗口
    resizable: isDevelopment, // 不允许拖拽窗口大小
    webPreferences: {
      nodeIntegration: false, // 禁用 Node.js 集成
      contextIsolation: true, // 启用上下文隔离
      webSecurity: false,//允许跨域
      preload: path.join(__dirname, 'preload.js')
    }
  })
  if(!isDevelopment) win.removeMenu() // 移除窗口菜单

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    win.loadURL('app://./index.html')
  }
  win.maximize()
}

 

 预加载脚本

preload.js


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

contextBridge.exposeInMainWorld('electronApi', {
  /**
   * 写入数据文件
   * @param {*} options { data, filename } data:待写入数据。filename:数据文件名称
   * @returns 
   */
  writeFile: async (options) => {
    try {
      const { data, filename } = options;
      return await ipcRenderer.invoke('write-file', { data, filename });
    } catch (error) {
      console.error('preload.js写入数据文件时出错:', error);
      return { ok: false, msg: error.message };
    }
  },
  /**
   * 读取数据文件
   * @param {object} filename 数据文件名称
   * @returns 
   */
  readFile: async (filename) => {
    try {
      return await ipcRenderer.invoke('read-file', filename);
    } catch (error) {
      console.error('preload.js读取数据文件时出错:', error);
      return { ok: false, msg: error.message };
    }
  },
  /**
   * 删除数据文件
   * @param {object} filename:数据文件名称
   * @returns 
   */
  removeFile: async (filename) => {
    try {
      return await ipcRenderer.invoke('remove-file', filename);
    } catch (error) {
      console.error('preload.js删除数据文件时出错:', error);
      return { ok: false, msg: error.message };
    }
  },
});

 渲染进程

 封装代码
common.js    
    /**
     * 数据写入
     * @param {object} data  待写入数据
     * @param {string} filename 文件名
     */
    writeF(data, filename){
      const options = {
        data: data,
        filename: filename
      };
      window.electronApi.writeFile(options).then(res => {
        console.log(res);
      })
    },
    /**
     * 数据读取
     * @param {string} filename 文件名
     */
    async readF(filename){
      return await window.electronApi.readFile(filename);
    },
    /**
     * 数据删除
     * @param {string} filename 文件名
     */
    removeF(filename){
      window.electronApi.removeFile(filename).then(res => {
        console.log(res);
        return res;
      })
    },
调用
file.vue

//写入
this.writeF({name:'123',age:23}, 'aa.json');

//读取
this.readF('aa.json').then(res => {
    console.log('res', res);
});

//删除
this.removeF('aa.json');

后文

        一起进步,冲冲冲!

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值