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

Electron 实战|Vue 桌面端开发从入门到上线

引言

大家好!作为一名前端开发者,你是否曾经想过将你的 Vue 应用打包成桌面应用?今天我要分享的是使用 Electron 将 Vue 应用转换为桌面应用的完整实战经验。从项目搭建到最终上线,我会详细介绍每个步骤,包括一些实用的自动化脚本和最佳实践。

需求背景

在开发过程中,我们经常遇到这样的场景:

  • 需要将 Web 应用打包成桌面应用
  • 希望应用能够离线运行
  • 需要访问本地文件系统
  • 要求应用具有原生桌面体验

Electron 正是解决这些需求的完美方案。它基于 Chromium 和 Node.js,让我们可以用 Web 技术开发跨平台的桌面应用。

工作原理

Electron 的核心架构包含两个进程:

  • 主进程(Main Process):负责创建和管理应用窗口,处理系统级 API
  • 渲染进程(Renderer Process):运行我们的 Vue 应用,类似于浏览器中的网页

两个进程通过 IPC(进程间通信)进行数据交换,主进程可以访问 Node.js API,渲染进程则专注于 UI 展示。

代码实现

1. 项目初始化

首先创建项目目录结构:

mkdir electron-vue-app
cd electron-vue-app
npm init -y

安装必要的依赖:

npm install electron electron-builder --save-dev
npm install vue@next @vitejs/plugin-vue vite --save-dev

2. 主进程配置

创建 main.js 文件:

const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const fs = require('fs')let mainWindowfunction createWindow() {mainWindow = new BrowserWindow({width: 1200,height: 800,webPreferences: {nodeIntegration: true,contextIsolation: false,enableRemoteModule: true}})// 开发环境加载本地服务器,生产环境加载打包文件if (process.env.NODE_ENV === 'development') {mainWindow.loadURL('http://localhost:3000')mainWindow.webContents.openDevTools()} else {mainWindow.loadFile('dist/index.html')}
}app.whenReady().then(createWindow)app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}
})

3. Vue 应用配置

创建 vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({plugins: [vue()],base: './',build: {outDir: 'dist'}
})

4. 自动化脚本实现

这里我们实现一个实用的文件备份脚本,展示 Electron 与 Node.js 的深度集成:

# backup_manager.py
import os
import shutil
import schedule
import time
import logging
from datetime import datetime
from pathlib import Path# 配置日志
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',handlers=[logging.FileHandler('backup.log'),logging.StreamHandler()]
)class BackupManager:def __init__(self, source_dir, backup_dir):self.source_dir = Path(source_dir)self.backup_dir = Path(backup_dir)self.backup_dir.mkdir(exist_ok=True)def backup_folder(self, folder_name):"""复制指定文件夹到备份目录"""try:source_path = self.source_dir / folder_nameif not source_path.exists():logging.warning(f"源文件夹 {folder_name} 不存在")return Falsetimestamp = datetime.now().strftime("%Y%m%d_%H%M%S")backup_path = self.backup_dir / f"{folder_name}_{timestamp}"shutil.copytree(source_path, backup_path)logging.info(f"成功备份 {folder_name}{backup_path}")return Trueexcept Exception as e:logging.error(f"备份 {folder_name} 失败: {str(e)}")return Falsedef schedule_backup(self, folder_name, interval_hours=24):"""定时备份任务"""schedule.every(interval_hours).hours.do(lambda: self.backup_folder(folder_name))logging.info(f"已设置 {folder_name}{interval_hours} 小时自动备份")def run_scheduler(self):"""运行定时任务"""logging.info("开始运行定时备份任务...")while True:schedule.run_pending()time.sleep(60)  # 每分钟检查一次# 使用示例
if __name__ == "__main__":backup_manager = BackupManager(source_dir="./src",backup_dir="./backups")# 立即备份一次backup_manager.backup_folder("components")# 设置定时备份backup_manager.schedule_backup("components", 12)  # 每12小时备份一次backup_manager.schedule_backup("views", 24)      # 每24小时备份一次# 运行定时任务backup_manager.run_scheduler()

5. Vue 组件实现

创建 App.vue

<template><div class="app"><header class="header"><h1>Electron Vue 桌面应用</h1><div class="actions"><button @click="openFileDialog" class="btn btn-primary">选择文件夹</button><button @click="startBackup" class="btn btn-success">开始备份</button><button @click="viewLogs" class="btn btn-info">查看日志</button></div></header><main class="main"><div class="file-list"><h3>文件列表</h3><ul><li v-for="file in fileList" :key="file.name" class="file-item"><span class="file-name">{{ file.name }}</span><span class="file-size">{{ formatFileSize(file.size) }}</span><span class="file-date">{{ formatDate(file.date) }}</span></li></ul></div><div class="backup-status"><h3>备份状态</h3><div class="status-item" v-for="status in backupStatus" :key="status.id"><span :class="['status', status.type]">{{ status.message }}</span><span class="timestamp">{{ status.timestamp }}</span></div></div></main></div>
</template><script>
import { ref, onMounted } from 'vue'export default {name: 'App',setup() {const fileList = ref([])const backupStatus = ref([])const openFileDialog = () => {// 调用 Electron 主进程打开文件对话框window.electronAPI.openFileDialog()}const startBackup = () => {backupStatus.value.push({id: Date.now(),type: 'info',message: '开始备份...',timestamp: new Date().toLocaleString()})// 调用备份脚本window.electronAPI.startBackup()}const viewLogs = () => {window.electronAPI.viewLogs()}const formatFileSize = (bytes) => {if (bytes === 0) return '0 Bytes'const k = 1024const sizes = ['Bytes', 'KB', 'MB', 'GB']const i = Math.floor(Math.log(bytes) / Math.log(k))return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]}const formatDate = (date) => {return new Date(date).toLocaleString()}onMounted(() => {// 监听来自主进程的消息window.electronAPI.onBackupComplete((event, result) => {backupStatus.value.push({id: Date.now(),type: result.success ? 'success' : 'error',message: result.message,timestamp: new Date().toLocaleString()})})})return {fileList,backupStatus,openFileDialog,startBackup,viewLogs,formatFileSize,formatDate}}
}
</script><style>
.app {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;margin: 0;padding: 20px;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);min-height: 100vh;
}.header {background: rgba(255, 255, 255, 0.1);backdrop-filter: blur(10px);border-radius: 15px;padding: 20px;margin-bottom: 20px;display: flex;justify-content: space-between;align-items: center;
}.header h1 {color: white;margin: 0;font-size: 2rem;
}.actions {display: flex;gap: 10px;
}.btn {padding: 10px 20px;border: none;border-radius: 8px;cursor: pointer;font-weight: 500;transition: all 0.3s ease;
}.btn-primary {background: #007bff;color: white;
}.btn-success {background: #28a745;color: white;
}.btn-info {background: #17a2b8;color: white;
}.btn:hover {transform: translateY(-2px);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}.main {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;
}.file-list, .backup-status {background: rgba(255, 255, 255, 0.9);border-radius: 15px;padding: 20px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}.file-item {display: flex;justify-content: space-between;padding: 10px;border-bottom: 1px solid #eee;
}.status-item {display: flex;justify-content: space-between;padding: 10px;border-bottom: 1px solid #eee;
}.status {padding: 4px 8px;border-radius: 4px;font-size: 0.9rem;
}.status.success {background: #d4edda;color: #155724;
}.status.error {background: #f8d7da;color: #721c24;
}.status.info {background: #d1ecf1;color: #0c5460;
}
</style>

6. 构建配置

创建 package.json 脚本:

{"name": "electron-vue-app","version": "1.0.0","main": "main.js","scripts": {"dev": "concurrently \"npm run dev:vite\" \"wait-on http://localhost:3000 && electron .\"","dev:vite": "vite","build": "vite build","build:electron": "npm run build && electron-builder","dist": "npm run build && electron-builder --publish=never"},"build": {"appId": "com.example.electron-vue-app","productName": "Electron Vue App","directories": {"output": "dist-electron"},"files": ["dist/**/*","main.js","node_modules/**/*"],"mac": {"category": "public.app-category.developer-tools"},"win": {"target": "nsis"},"linux": {"target": "AppImage"}}
}

运行效果截图

在这里插入图片描述

应用运行后的效果包括:

  1. 主界面:现代化的渐变背景,半透明毛玻璃效果的头部区域
  2. 文件管理:左侧显示文件列表,包含文件名、大小、修改日期
  3. 备份状态:右侧实时显示备份进度和结果
  4. 操作按钮:三个主要功能按钮,具有悬停动画效果
  5. 日志查看:点击查看日志按钮会打开日志文件

界面采用响应式设计,支持不同屏幕尺寸,整体风格简洁现代。

总结

通过这个实战项目,我们成功地将 Vue 应用打包成了桌面应用,并集成了实用的文件备份功能。关键技术点包括:

  • Electron 主进程与渲染进程通信:实现了 Web 技术与系统 API 的无缝集成
  • 自动化脚本:使用 Python 的 shutil、schedule、logging 模块实现了文件备份和定时任务
  • 现代化 UI:采用 CSS Grid 布局和毛玻璃效果,提供良好的用户体验

这个脚本具有很强的扩展性,你可以进一步:

  • 云端备份:集成 AWS S3、阿里云 OSS 等云存储服务
  • 压缩打包:使用 zipfile 或 tar 模块压缩备份文件
  • 增量备份:只备份修改过的文件,提高效率
  • 加密存储:使用 cryptography 模块加密敏感文件

希望这篇文章对你在 Electron + Vue 桌面应用开发方面有所帮助!

参考资料

  • Electron 官方文档
  • Vue 3 官方文档
  • Vite 构建工具
  • Python shutil 模块
  • Python schedule 库
  • Python logging 模块

作者: 王新焱
博客: https://blog.csdn.net/qq_34402069
时间: 2025年10月22日


http://www.dtcms.com/a/515726.html

相关文章:

  • 【北京迅为】iTOP-4412精英版使用手册-第五十二章 注册字符类设备
  • 计算机组成原理实验
  • ChatGPT 技术解析与应用:从原理到实践的全景视角
  • 2026版基于python的协同过滤音乐推荐系统
  • 塔防游戏Python开发核心状态与算法实现:植物大战僵尸类游戏技术解析
  • python+vue共享自习室预约系统设计(源码+文档+调试+基础修改+答疑)
  • 漳州网站建设到博大赞wordpress文章不显示自定义字段
  • 新企业如何在国税网站上做套餐wordpress 安装 乱码
  • 函数装饰器
  • 正则表达式入门到精通教程(Linux实操版)
  • 逆向开发在逆向加密狗中的作用
  • 网站模板 古典大学生app开发创业计划书
  • Linux 信号控制
  • Android Studio模拟器无法联网(能打开IP网页,但不能打开域名,DNS解析错误)问题2025年10月22日
  • php如何做局域网的网站网站设计与网页制作代码大全
  • 在没有网络的环境下安装包pymysql
  • Gradle 构建脚本迁移:从 Groovy DSL 到 Kotlin DSL,语法与技巧对比
  • 个人网站审批怎么制作ppt模板 教程
  • 内网构建https
  • [运维]宝塔 Apache环境使用CDN获取访客真实IP方法
  • 【学习系列】SAP RAP 17:RAP应用部署集成至Fiori Launchpad 【S4HC Public Edition】
  • 正点原子RK3568学习日志15-杂项设备驱动
  • 绍兴建设开发有限公司网站网站网站娱乐建设
  • 迭代器失效问题
  • Ubuntu 16.04交叉编译arm-linux-gnueabihf的QT5.6.2
  • 神经网络详解
  • 网站如何防止黑客攻击宁波新闻
  • 为打印预览对话框 PrintPreviewDialog 添加保存到 PDF 文件按钮源代码详解
  • Nevercenter CameraBag Photo for mac照片滤镜美化软件
  • 设计模式-策略模式:从鞋厂促销活动看算法的灵活切换