electron 开发轻量级本地数据存储桌面端应用(简洁版)

news2024/11/24 12:07:53

背景

接了一个项目需要开发一个功能简单的桌面端应用,主要包含的功能有 内置数据,本地化操作数据,对数据进行CRUD操作。
效果展示如下:
在这里插入图片描述
在这里插入图片描述

技术选型:

  1. 开发桌面端有如下几种技术方案:**

    Electron:使用HTML、CSS和JS构建跨平台的桌面应用程序,基于Chromium和Node.js。
    NW.js:(也称node-webkit)类似于Electron。
    React Native:使用React和JS。
    Flutter:使用Dart编程语言,可构建高度定制的桌面应用程序。
    
    本文这里选择Electron。 
    
  2. “vue”: “^3.2.47”,
    “vue-router”: “^4.1.6”,
    “ant-design-vue”: “^4.0.0”,
    “lowdb”: “^1.0.0”, //本地化存储数据插件

项目搭建

本项目使用Vue Cli 创建Vue项目,命令如下:

npm i @vue/cli -g
vue create desk
cd desk
vue add electron-builder
npm run electron:serve

运行之后效果:
在这里插入图片描述
项目目录如下:
和vue项目目录差不多,差异的是electron主进程的代码是放在background.js中。
在这里插入图片描述

项目难点:

一.Electron 实现对数据进行本地持久化存储方案选择——lowdb

Electron 是一个用于构建跨平台桌面应用程序的开源框架,它允许你使用前端技术(HTML、CSS 和 JavaScript)创建桌面应用程序。如果你想在 Electron 应用程序中对数据进行本地持久化存储,你可以使用以下方法:

  1. 使用 Electron 的内置 API: Electron 提供了一些内置的 API,可以让你轻松地进行本地数据持久化存储,最常见的是使用 localStoragesessionStorage,类似于在浏览器中的用法。这种方法适合于存储少量数据,例如配置信息或用户首选项。

    示例:

    // 本地存储数据
    localStorage.setItem('key', 'value');
    
    // 从本地获取数据
    const data = localStorage.getItem('key');
    
    // 删除数据
    localStorage.removeItem('key');
    
  2. 使用 Node.js 模块: Electron 可以使用 Node.js 模块,这意味着你可以使用 Node.js 提供的文件系统和其他模块来进行更高级的本地数据持久化存储。最常见的方式是使用 fs 模块来读写文件。

    示例:

    const fs = require('fs');
    
    // 写入数据到本地文件
    fs.writeFile('data.txt', 'Hello, Electron!', (err) => {
      if (err) throw err;
      console.log('数据已写入文件');
    });
    
    // 从本地文件读取数据
    fs.readFile('data.txt', 'utf8', (err, data) => {
      if (err) throw err;
      console.log('从文件中读取的数据:', data);
    });
    
  3. 使用数据库: 如果你需要存储大量结构化数据,你可以考虑使用一种数据库系统,如 SQLite、IndexedDB 或 LevelDB。SQLite 特别适合桌面应用程序,因为它是一个嵌入式数据库引擎,可以轻松地集成到 Electron 应用中。

    示例(使用 SQLite):

    const sqlite3 = require('sqlite3').verbose();
    const db = new sqlite3.Database('mydatabase.db');
    
    // 创建表并插入数据
    db.serialize(() => {
      db.run('CREATE TABLE IF NOT EXISTS users (id INT, name TEXT)');
      db.run('INSERT INTO users VALUES (1, "John")');
    });
    
    // 查询数据
    db.all('SELECT * FROM users', (err, rows) => {
      if (err) throw err;
      console.log('查询结果:', rows);
    });
    
    // 关闭数据库连接
    db.close();
    

以上是在 Electron 应用程序中进行本地持久化存储的一些常见方法。

本项目使用lowdblowdb是一个轻量级的本地JSON数据库,适合小型项目和简单数据持久化需求。

二.lowdb的基本使用规则:

  1. 安装和导入:

    在您的Electron项目中,首先确保安装了lowdblodash依赖:

    npm install lowdb lodash
    

    然后在您的JavaScript文件中导入lowdblodash

    const low = require('lowdb');
    const FileSync = require('lowdb/adapters/FileSync');
    const adapter = new FileSync('db.json'); // 指定数据文件
    const db = low(adapter);
    
  2. 初始化数据库:

    在初始化lowdb时,您可以使用defaults方法来指定初始数据和默认值:

    db.defaults({ users: [] }).write();
    

    这将创建名为users的初始数据对象,如果数据文件中不存在该对象,将使用默认值。

  3. 插入数据:

    使用push方法将数据插入到数据库中:

    db.get('users')
      .push({ id: 1, name: 'Alice' })
      .write();
    
  4. 查询数据:

    使用get方法和value方法查询数据:

    const users = db.get('users').value();
    
  5. 更新数据:

    使用find方法和assign方法来更新数据:

    db.get('users')
      .find({ id: 1 })
      .assign({ name: 'Alicia' })
      .write();
    
  6. 删除数据:

    使用remove方法来删除数据:

    db.get('users')
      .remove({ id: 1 })
      .write();
    
  7. 链式操作:

    lowdb支持链式操作,您可以在一个语句中执行多个操作,例如插入、查询和更新数据:

    db.get('users')
      .push({ id: 2, name: 'Bob' })
      .find({ id: 2 })
      .assign({ name: 'Bobby' })
      .write();
    
  8. 使用过滤器:

    您可以使用filter方法来过滤数据:

    const filteredUsers = db.get('users')
      .filter(user => user.name.includes('B'))
      .value();
    

了解更多详细信息可看lowdb的文档。

三. 读取本地数据

  • background.js文件中实现本地数据读取代码如下:
import LodashId from 'lodash-id'
import FileSync from 'lowdb/adapters/FileSync'
import fs from 'fs-extra'
import localDb from './local-db.json'

const APP = process.type === 'renderer' ? remote.app : app
const STORE_PATH = APP.getPath('userData')  //获取electron应用的用户目录
// 判断路径是否存在,若不存在,就创建一个新的
if (process.type !== 'renderer') {
  if (!fs.pathExistsSync(STORE_PATH)) {
    fs.mkdirpSync(STORE_PATH)
  }
}
const adapter = new FileSync(path.join(STORE_PATH, 'localData.json'))
let db = Datastore(adapter) // lowdb接管该文件数据
db._.mixin(LodashId)  //LodashId自动生成id
db.defaults(localDb).write() // 一定要显式调用write方法将数据存入JSON

四. 对数据进行操作,就涉及到主进程与渲染进程之间进行通信

  • background.js文件中监听渲染进程的请求代码如下:
// 监听渲染进程的请求
ipcMain.on('ipc-getSurfaceData', (event) => {
  // 执行数据库写入操作
  try {
    const data = db.get('SurfaceData').value()
    // 读取成功的响应给渲染进程
    event.sender.send('getSurface', { success: true, res: data });
  } catch (error) {
    // 发送写入失败的响应给渲染进程
    return event.sender.send('getSurface', { success: false, error: error.message });
  }
});
  • 渲染进程 src/api/service.js 发送请求给主进程执行数据库写入操作如下:
    这里有点类似mock 模拟发送请求,不过这里是向主进程发送请求,因为只有主进程才有对本地数据进行增删改查的操作。
export function getSurfaceData() {
  // 发送请求给主进程执行数据库写入操作
  ipcRenderer.send('ipc-getSurfaceData');
  return new Promise((resolve, reject) => {
    // 监听来自主进程的响应
    ipcRenderer.on('getSurface', (event, res) => {
      if (res.success) {
        resolve({
          code: 200,
          data: res.res
        })
      } else {
        return reject({
          code: 400,
          message: res.error
        })
      }
    });
  })
}
  • vue文件下调用渲染进程的方法,代码如下:
const getSurface = async () => {
  const res = await getSurfaceData()
  if (res.code == 200) {
    SurfaceData.value = res.data
    innerSurfaceData.value = SurfaceData.value.filter(
      (item) => item.type == 'inner'
    )
    outSurfaceData.value = SurfaceData.value.filter((item) => item.type == 'out')
  } else {
    message.error(res.message)
  }
}

以上就是使用lowdb对本地数据进行操作的具体实现。

五. 打包相关配置

在什么系统下打包就会生成相应系统下的桌面端,也可以执行命令去打包相应的桌面端
page.json 添加如下打包命令:
“electron:build:win32”: “vue-cli-service electron:build --mode --win --ia32”,
“electron:build:win64”: “vue-cli-service electron:build --mode --win --x64”,
“electron:build:mac”: “vue-cli-service electron:build --mode --mac”,

  • vue.config.js 文件代码如下:
module.exports = {
  lintOnSave: true,
  productionSourceMap: false,
  pluginOptions: {
    electronBuilder: {
      nodeIntegration: true,
      chainWebpackMainProcess: (config) => {
        config.output.filename((file) => {
          if (file.chunk.name === 'index') {
            return 'background.js';
          } else {
            return '[name].js';
          }
        });
      },
      builderOptions: {
        appId: 'com.electron.htc',//包名
        buildVersion: '20230726',
        productName: 'xxx软件',//生成exe的名字
        copyright: 'Copyright © 2023- year',
        icon: 'static/favicon.ico',
        extraFiles: [
          {
            from: 'src/assets/favicon.ico',
            to: 'static/favicon.ico',
          },
        ],
        win: {
          icon: 'src/assets/favicon.ico',
          executableName: 'xxx软件',
          requestedExecutionLevel: 'requireAdministrator',
        },
        nsis: {
          oneClick: false,// 是否一键安装
          perMachine: true, //代表是否显示辅助安装程序的安装模式安装程序页面(选择按机器还是按用户)。true时代表始终按用户安装。
          artifactName:
            'xxx软件V${version}_Build${buildVersion}.${ext}',
          uninstallDisplayName: 'xxx软件 ${version}',
          allowToChangeInstallationDirectory: true, //是否允许修改安装目录
          createDesktopShortcut: true, // 是否创建桌面图标
          createStartMenuShortcut: true,// 是否创建开始菜单图标
          shortcutName: "xxx软件", // 快捷方式名称
          runAfterFinish: false,//是否安装完成后运行
          menuCategory: 'xxx有限公司',
        },
      },
    },
    // chainWebpackMainProcess: (config) => {
    //   config.output.filename('background.js');
    // }
  },
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true,
        },
      },
    },
  },
}

这就是我第一次开发桌面端的经历,搭建的项目复杂程度仅供小型桌面端使用。复杂一些的项目,就需要考虑主进程再去细分,一个background.js难以满足。详细的可以看electron的官方文档!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1163163.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【UE5 C++】C++代码调用蓝图方法或事件

此方法为:先创建C类MyTest,再以MyTest类为父类创建蓝图;在其他类中,可以通过MyTest调用蓝图对应方法。 1.创建c代码 通过UE创建继承自Actor的C代码 2.添加可以在UE中重写方法的说明 需使用声明:UFUNCTION(Bluepr…

【JavaWeb篇】HTTP请求构造方式

✅作者简介:大家好,我是小杨 📃个人主页:「小杨」的csdn博客 🐳希望大家多多支持🥰一起进步呀! HTTP请求构造方式 1,通过form表单构造 form 表单是HTML中的一个常用标签&#xff0…

【深度学习】pytorch——线性回归

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 深度学习专栏链接: http://t.csdnimg.cn/dscW7 pytorch——线性回归 线性回归简介公式说明完整代码代码解释 线性回归简介 线性回归是一种用于建立特征和目标变量之间线性关系的统计学习方法。它假设…

GoLong的学习之路(十七)基础工具之GORM(操作数据库)(更新)

书接上回,上回写道,GORM的查询和创建(插入数据),这回继续些增删改查的改和删的操作。 文章目录 更新update修改单个列修改多个列修改选定字段批量更新新阻止全局更新 使用 SQL 表达式更新注意 根据子查询进行更新不使用…

Modbus转Profinet网关与流量变送器兼容转ModbusTCP协议博图配置案例

首先,我们需要明确电磁流量计的通信协议是Modbus,而西门子1200PLC的通信协议是Profinet。这两种协议在功能和特性上存在一定的差异,因此需要使用兴达易控Modbus转Profinet网关设备进行转换。兴达易控的XD-MDPN100是Profinet转ModbusTCP的网关…

功率放大器的种类和作用是什么

功率放大器是一种电子设备,用于将输入信号的功率增加到更高的水平,以驱动负载或输出设备。功率放大器广泛应用于各种领域,包括通信、音频、无线电频谱分析、激光器和雷达等。 根据应用需求和工作原理不同,功率放大器可分为几种不同…

笔记:IDEA如何修改代码后,不重启服务器局部更新资源

前言 平常用IDEA开发网页写调样式和测功能最讨厌改一丁点东西就要重启整个服务器,所以本文主要就是解决此问题从而提高开发效率,避免浪费过多时间。 具体步骤 1、打开设置框 2、先新增exploded结尾的,并apply应用,把没有结尾的…

【Kubernetes部署】二进制部署单Master Kurbernetes集群 超详细

二进制部署K8s 一、基本架构和系统初始化操作1.1 基本架构1.2 系统初始化操作 二、部署etcd集群2.1 证书签发Step1 下载证书制作工具Step2 创建k8s工作目录Step3 编写脚本并添加执行权限Step4 生成CA证书、etcd 服务器证书以及私钥 2.2 启动etcd服务Step1 上传并解压代码包Step…

云尘-Node1 js代码

继续做题 拿到就是基本扫一下 nmap -sP 172.25.0.0/24 nmap -sV -sS -p- -v 172.25.0.13 然后顺便fscan扫一下咯 nmap: fscan: 还以为直接getshell了 老演员了 其实只是302跳转 所以我们无视 只有一个站 直接看就行了 扫出来了两个目录 但是没办法 都是要跳转 说明还是需要…

轻松搭建Nextcloud私有云盘并实现远程访问【内网穿透】

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

opencv第一个例子

目的 这是用用QTopencv实现的一个完整的展示图片的例子,包括了项目的配置文件,完整的代码,以用做初次学习opencv用。 代码 工程文件: QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsTARGET openCv1 TEMPL…

双路比例阀放大器

双路比例阀放大器是一种常见的电子设备,它能够将输入信号放大到所需的水平,并输出两个相等或不同的放大信号。这种放大器通常由一个放大器和一个驱动电路组成,可以用于各种应用中,如液压控制、气动控制等。 在液压控制方面&#…

物联网系统的基本构件

1.基本组件 云服务器 数据库消息服务器应用服务器管理平台 云APP 云服务器的维护终端微信客户端网页管理平台 页面式的更全面的管理。组态软件和PLC软件 编程软件终端设备 PLC 主要指标,模拟数字接口数量 DO有 继电器和1.5,2.5.5V数字输出一般支持扩展IO模块模拟量…

利用win32的GetLastInputInfo函数实现锁屏(C#)

前两天看到群里面讨论这个问题,刚好我们上一家公司的系统也有这个功能,就研究了一下,我们这边实现这个功能的目的如下:当用户长时间不操作系统时,自动退出系统并退回到登录界面,想要使用系统,就…

软文投放、发稿:如何写一篇优质的软文

在当今的营销世界中,软文是一种强大的工具,可以用来宣传产品、建立品牌形象,以及与受众建立更深层次的联系。然而,要写一篇优质的软文并不容易。本文将介绍如何撰写一篇引人入胜的软文,以吸引读者的兴趣和赢得他们的信…

用 Java 实现 Syslog 功能

1、业务场景 用一个 Spring Boot 的项目去实现对管控设备的监控、日志收集等。同时需要将接收到的日志进行入库,每天存一张表,如device_log_20231026… 2、Syslog客户端(接收日志的服务器,即运行Java程序的服务器) 2…

JavaScript 基础 - 第4天

理解封装的意义,能够通过函数的声明实现逻辑的封装,知道对象数据类型的特征,结合数学对象实现简单计算功能。 理解函数的封装的特征掌握函数声明的语法理解什么是函数的返回值知道并能使用常见的内置函数 函数 理解函数的封装特性&#xff0c…

软件测试/测试开发丨UbuntuServer环境准备

点此获取更多相关资料 前提 现有设备是一套 i54090 的组合,安装了 Ubuntu 22.04.3 LTS Server 版本,后文的安装步骤都是基于这套系统和配置进行操作。 系统准备 查看是否安装了 gcc 命令行中执行 gcc -v 正常输入如图效果的,说明已经成功…

kubeadm部署kubernetes1.28

k8s在1.24版本以后删除了内置dockershim插件,原生不再支持docker运行时,需要使用第三方cri接口cri-docker https://github.com/Mirantis/cri-dockerd.git 安装前,需要先升级systemd和主机内核,本操作文档安装的是最新的版本kube…

微信小程序渲染的富文本里面除了img标签外什么都没有,该如何设置img的大小

微信小程序富文本渲染&#xff1a; <rich-text nodes"{{content}}"style"{{style}}" ></rich-text> content是接口得到的值 let cont object.contentlet a cont.replace(/<img/gi,<img style"max-width:94%;height:auto;margi…