前端架构师视角:Electron 知识框架全解析(含实战+面试)

前端架构师视角:Electron 知识框架全解析(含实战+面试)

本文将从前端架构师的视角,系统性梳理 Electron 知识框架,覆盖「发展历史与版本迭代、诞生背景与核心价值、核心语法与架构原理、实战开发(从环境搭建到项目打包)、调试技巧与高级开发、知识总结与高频面试题」六大模块,层层深入、图文并茂,既有底层原理剖析,也有实战落地指南,帮你彻底吃透 Electron,轻松应对项目开发与面试考核。

作为前端架构师,梳理 Electron 完整知识框架,要求内容专业、逻辑连贯、细节详实,覆盖以下核心模块,撰写一篇图文并茂的技术博客:1.

发展历史(梳理关键版本迭代、核心特性更新,明确各版本适配场景与升级注意事项);2. 诞生背景(分析 Electron

出现的技术痛点、行业需求,对比传统桌面开发与 Electron 开发的差异,凸显其核心价值);3.

核心语法与架构原理(拆解主进程、渲染进程、预加载脚本的作用与通信机制,详解核心 API 与配置规范);4. 实战开发(从环境搭建、Hello

World 入门,到完整项目开发、打包部署,附详细代码示例与步骤);5.

调试技巧与高级开发(主进程/渲染进程调试方法、性能优化、安全加固、原生模块集成等高级技巧);6.

知识总结与高频面试题(梳理核心知识点,整理前端架构师视角下的高频面试题及详细解析,适配面试场景)。

bash 复制代码
Electron 知识框架
  1. 发展历史与版本
    起源:Atom Shell → 2015 更名 Electron
    版本迭代
      1.0~5.0:基础架构、多进程模型
      6.0~18.0:TS 支持、安全增强、弃用 remote
      19.0~最新:轻量化、M1 适配、性能优化
    版本选型
      企业项目:LTS 稳定版
      工具项目:最新稳定版
      禁止使用 < 12.0 版本
  2. 诞生背景与价值
    技术痛点
      原生跨平台成本高
      Web 无法调用系统能力
      技术栈割裂
    方案对比
      原生开发:C#/Swift/C++、性能高、成本高
      Electron:Web 技术栈、一套代码跨三端
    核心价值
      技术栈统一
      跨平台一致
      原生能力可调用
      生态成熟
  3. 核心架构与语法
    进程模型
      主进程:生命周期、窗口、系统 API
      渲染进程:UI 渲染、用户交互
      预加载脚本:安全桥接、API 暴露
    通信机制
      IPC 主从通信
      ipcMain / ipcRenderer
      contextBridge 安全隔离
    核心 API
      app:生命周期
      BrowserWindow:窗口管理
      dialog / tray / notification
    安全配置
      contextIsolation: true
      nodeIntegration: false
      sandbox 启用
  4. 实战开发流程
    环境搭建
      Node.js LTS
      安装 Electron
      镜像加速
    入门项目
      Hello World 三文件结构
      主进程 + 预加载 + 页面
    企业项目
      目录规范
      文件操作、托盘、弹窗
    打包部署
      electron-builder
      win/mac/linux 打包
      图标、安装包配置
  5. 调试与高级开发
    调试方法
      主进程:VSCode 调试
      渲染进程:DevTools
    性能优化
      启动速度优化
      安装包瘦身
      内存管理
    安全加固
      XSS 防护
      CSP 策略
      权限最小化
    高阶能力
      原生模块集成
      自动更新
      硬件调用
  6. 总结与面试题
    核心总结
      多进程模型
      安全通信原则
      版本与架构设计
    高频面试
      主进程 vs 渲染进程
      为什么要预加载脚本
      IPC 如何保证安全
      性能/体积优化方案
      企业项目架构思路

二、Electron 知识框架全解析(前端架构师版)

2.1 发展历史与版本迭代

Electron 的前身是 2013 年由 GitHub 开发的 Atom Shell,最初用于支撑 Atom 编辑器的跨平台运行,2015 年正式更名为 Electron,随后捐献给 OpenJS Foundation 进行维护,逐步发展为开源跨平台桌面应用开发的行业标准框架。其版本迭代与 Chromium、Node.js 深度绑定,遵循「八周一个大版本」的迭代周期,与 Chromium 稳定版的发布节奏保持同步,确保 Web 技术与系统兼容性的及时更新。

2.1.1 关键版本迭代(核心特性梳理)

Electron 的版本迭代核心是同步 Chromium 和 Node.js 的版本,同时优化自身架构、性能与安全,以下是前端架构师必须关注的关键版本及核心更新,结合实际项目选型场景说明:

1. 早期版本(1.0 - 5.0):奠定基础,完善核心架构
  • 1.0 版本(2016年):标志着 Electron 正式成熟,确立了「Chromium + Node.js」的核心架构,引入主进程与渲染进程的分离设计,为多窗口应用提供了基础支撑,同时完善了窗口管理、菜单定制等核心功能,奠定了后续所有版本的架构基础。此时的 Electron 已能支撑 Atom 编辑器的稳定运行,证明了 Web 技术开发桌面应用的可行性。

  • 2.0 - 5.0 版本(2018 - 2019年):重点优化性能与稳定性,解决早期版本内存占用过高、启动速度慢的问题。引入更高效的垃圾回收机制,优化进程间通信(IPC)性能,同时加强沙箱机制,提升应用安全性;支持更多系统原生 API,如桌面通知、系统托盘等,让应用更贴近原生体验。此阶段,VS Code 基于 Electron 逐步崛起,推动 Electron 生态快速发展。

2. 中期版本(6.0 - 18.0):现代化升级,生态完善
  • 6.0 版本(2019年):对原生 Node.js 模块的支持变得更稳定可靠,同时开始全面拥抱现代 JavaScript 特性,优化 TypeScript 支持,让前端开发者能更顺畅地使用 TypeScript 进行开发,提升大型项目的可维护性。

  • 9.0 版本(2020年):默认开启「上下文隔离(Context Isolation)」和「禁用 Node.js 集成(nodeIntegration: false)」,将安全配置提升到新高度,从底层规避 XSS 攻击等安全风险,这也是前端架构师在项目选型中必须关注的安全基线。

  • 12.0 - 18.0 版本(2021 - 2022年):同步 Chromium 最新版本,支持更多 Web 新特性(如 WebAssembly 优化、CSS 新属性);优化 Mac M1 芯片适配,实现跨架构兼容;完善打包工具链,简化应用分发流程;同时废弃了老旧 API(如 remote 模块),推出更安全的通信方式,倒逼开发者规范开发流程。

3. 近期版本(19.0 - 40.0+,截至2026年):轻量化、高性能、高安全
  • 20.0+ 版本:重点推进轻量化,优化应用打包体积和启动速度,解决 Electron 长期以来「臃肿」的痛点;加强与系统原生功能的深度集成,如 Windows 通知中心、Mac 菜单栏增强等;完善调试工具,提升开发体验。

  • 40.0+ 版本(2026年最新稳定版):同步 Chromium 124+ 版本,支持最新的 Web 性能优化特性;优化内存管理,进一步降低内存占用;增强安全机制,支持更严格的内容安全策略(CSP);完善 TypeScript 类型定义,提升大型项目的开发效率;同时优化了多进程调度,提升多窗口应用的流畅度。

2.1.2 版本选型建议(前端架构师视角)

作为架构师,版本选型直接决定项目的稳定性、安全性和可维护性,核心建议如下:

  • 企业级项目(如办公软件、编辑器):优先选择 LTS 长期支持版本(如 28.0.0+、30.0.0+),LTS 版本支持周期长(通常 18 个月),bug 修复及时,兼容性更稳定,避免因版本迭代导致的API 废弃问题。

  • 小型项目、工具类应用(如小工具、辅助软件):可选择较新的稳定版(如 40.0.0+),享受最新特性和性能优化,降低开发成本。

  • 避免使用低于 12.0 的版本:此类版本安全配置不完善,存在较多安全漏洞,且很多老旧 API 已被废弃,后续维护成本极高。

2.2 诞生背景与核心价值

2.2.1 诞生背景:解决跨平台桌面开发的核心痛点

在 Electron 出现之前,桌面应用开发面临三大核心痛点,这也是其诞生的核心驱动力:

  1. 跨平台开发成本高:传统桌面应用开发需针对 Windows(C#)、Mac(Swift/Objective-C)、Linux(C++)分别开发,一套代码无法复用,开发周期长、维护成本高,前端开发者难以涉足桌面开发领域。

  2. Web 技术与桌面能力脱节:Web 应用具有开发效率高、跨浏览器兼容的优势,但无法访问系统原生资源(如本地文件、系统托盘、桌面通知),难以实现桌面级的交互体验;而原生桌面应用虽能访问系统资源,但开发门槛高、迭代速度慢。

  3. 技术栈割裂:前端开发者需学习全新的原生开发技术栈才能开发桌面应用,技术栈切换成本高,导致 Web 技术的优势无法在桌面端发挥。

2013 年,GitHub 为了解决 Atom 编辑器的跨平台开发问题,开发了 Atom Shell(Electron 前身),核心思路是「将 Chromium(Web 渲染引擎)与 Node.js(系统级 API 运行时)结合」,让前端开发者仅用 HTML、CSS、JavaScript 就能开发跨平台桌面应用,打通 Web 与桌面端的技术壁垒,这就是 Electron 诞生的核心背景。

2.2.2 核心价值:前端架构师的「跨端利器」

对于前端架构师而言,Electron 的核心价值不在于「能开发桌面应用」,而在于「用前端技术栈,低成本、高效率地实现跨平台桌面应用,同时兼顾性能与原生体验」,具体体现在以下4点:

  • 技术栈统一:无需学习原生开发语言,前端开发者可直接复用 HTML、CSS、JavaScript/TypeScript 技术栈,甚至可复用现有 Web 项目的代码,大幅降低跨端开发成本,提升开发效率。

  • 跨平台一致性:一套代码可打包为 Windows、Mac、Linux 三大系统的应用,无需针对不同系统单独适配,架构师可集中精力设计统一的应用架构,减少多端适配的复杂度。

  • 原生能力访问:通过 Electron 提供的 API,可直接访问系统原生资源(本地文件、系统托盘、桌面通知、打印机、摄像头等),让 Web 应用拥有桌面级的交互体验,弥补 Web 技术的局限性。

  • 生态完善,可扩展性强:Electron 拥有庞大的生态体系,无论是打包工具(electron-builder、electron-packager)、状态管理工具,还是第三方插件(如 electron-store、electron-debug),都能满足不同项目的需求;同时支持原生模块集成,可通过 C++ 编写原生模块,提升应用性能,适配复杂场景(如视频编辑、硬件交互)。

2.2.3 对比传统桌面开发与 Electron 开发

对比维度 传统桌面开发(C#/Swift/C++) Electron 开发
技术栈 需学习对应系统的原生语言,技术栈割裂 前端技术栈(HTML/CSS/JS/TS),统一且门槛低
跨平台能力 一套代码无法跨平台,需单独开发 一套代码适配三大系统,一致性强
开发效率 开发周期长,迭代速度慢 开发效率高,可复用 Web 代码,迭代速度快
原生体验 原生体验好,与系统深度融合 接近原生体验,可通过 API 提升融合度,部分场景略逊
性能 性能优,内存占用低 性能良好,启动速度、内存占用略高于原生(可通过优化改善)
维护成本 多端维护,成本高 单套代码维护,成本低

2.3 核心语法与架构原理

Electron 的核心架构是「主进程 + 渲染进程 + 预加载脚本」,三者协同工作,构成完整的应用体系。作为前端架构师,必须吃透这一架构,才能设计出高性能、高可维护性的 Electron 应用。

2.3.1 核心架构:主进程与渲染进程(重中之重)

Electron 应用基于多进程模型,与 Chrome 浏览器的架构类似,核心分为「主进程」和「渲染进程」,两者职责明确、互不干扰,通过特定方式通信,具体如下:

1. 主进程(Main Process)

主进程是 Electron 应用的入口,整个应用只有一个主进程,运行在 Node.js 环境中,拥有完整的系统权限,核心职责如下:

  • 控制应用生命周期:负责应用的启动、关闭、重启,以及处理应用级别的事件(如 ready、window-all-closed、quit 等)。

  • 管理窗口:通过 BrowserWindow 模块创建、关闭、最小化、最大化窗口,控制窗口的大小、位置、样式等。

  • 访问系统原生资源:调用 Electron 提供的系统级 API,访问本地文件、系统托盘、桌面通知、打印机、摄像头等原生资源。

  • 管理渲染进程:创建渲染进程,与渲染进程进行通信,控制渲染进程的生命周期。

主进程的入口文件由 package.json 中的 main 字段指定(默认是 main.js),这是应用启动时首先执行的文件。

2. 渲染进程(Renderer Process)

渲染进程负责应用的 UI 渲染和用户交互,每个窗口对应一个渲染进程,运行在 Chromium 环境中,核心职责如下:

  • 渲染 UI 界面:通过 HTML、CSS 渲染应用界面,与普通 Web 页面的渲染逻辑一致。

  • 处理用户交互:响应鼠标、键盘等用户操作,执行前端逻辑(如事件绑定、接口请求等)。

  • 与主进程通信:通过 IPC 机制向主进程发送请求,获取系统资源或执行系统级操作,接收主进程的响应。

注意:渲染进程默认处于沙箱环境中,无法直接访问系统原生资源和 Node.js API(出于安全考虑),必须通过主进程间接访问;若需在渲染进程中使用 Node.js API,需在创建窗口时配置 webPreferences.nodeIntegration: true(不推荐,存在安全风险)。

3. 预加载脚本(Preload Script)

预加载脚本是介于主进程和渲染进程之间的中间层,运行在渲染进程中,但拥有访问 Node.js API 的权限,核心作用是「安全地暴露主进程的 API 给渲染进程」,避免直接开启 Node.js 集成带来的安全风险。

预加载脚本通过 BrowserWindow 的 webPreferences.preload 字段指定,在渲染进程加载页面之前执行,可通过 contextBridge 模块将主进程的 API 暴露到渲染进程的全局对象中,供前端页面调用。

4. 核心架构示意图(图文结合)

以下示意图清晰展示了主进程、渲染进程、预加载脚本的关系,以及与 Chromium、Node.js 的关联:

示意图说明:1. 主进程依赖 Node.js 运行时,可访问系统原生资源;2. 渲染进程依赖 Chromium 引擎,负责 UI 渲染;3. 预加载脚本运行在渲染进程中,作为两者通信的桥梁;4. 主进程与渲染进程通过 IPC 机制通信,预加载脚本通过 contextBridge 暴露 API。

2.3.2 核心语法与 API(前端架构师必掌握)

Electron 的语法本质是「Node.js + Web API + Electron 专属 API」,前端开发者可快速上手,以下是核心语法和高频 API,按模块分类说明:

1. 应用生命周期 API(app 模块)

app 模块是控制应用生命周期的核心模块,所有应用级别的事件和操作都通过该模块实现,高频 API 如下:

  • app.whenReady():监听应用就绪事件,应用启动后,所有初始化操作(如创建窗口)需在该事件回调中执行。

  • app.on('window-all-closed'):监听所有窗口关闭事件,通常在该事件中执行 app.quit()(Windows/Linux 系统),Mac 系统可保留应用后台运行。

  • app.on('activate'):Mac 系统专属事件,当应用被激活(如点击 Dock 图标)时触发,用于重新创建窗口(若所有窗口已关闭)。

  • app.quit():退出应用,终止主进程和所有渲染进程。

  • app.getPath(name):获取系统特定路径(如用户文档、桌面、缓存目录),用于文件存储等场景。

示例代码(主进程 main.js):

javascript 复制代码
const { app, BrowserWindow } = require('electron');
const path = require('path');

// 应用就绪后创建窗口
app.whenReady().then(() => {
  createWindow();
  // Mac 系统特殊处理:激活应用时重新创建窗口
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// 所有窗口关闭后退出应用(Windows/Linux)
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

// 创建窗口函数
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 配置预加载脚本
      preload: path.join(__dirname, 'preload.js'),
      // 开启上下文隔离(安全配置)
      contextIsolation: true,
      // 禁用 Node.js 集成(安全配置)
      nodeIntegration: false
    }
  });
  // 加载渲染进程页面
  mainWindow.loadFile('index.html');
  // 打开开发者工具(开发环境)
  if (process.env.NODE_ENV === 'development') {
    mainWindow.webContents.openDevTools();
  }
}
2. 窗口管理 API(BrowserWindow 模块)

BrowserWindow 模块用于创建和管理窗口,是 Electron 应用的核心模块之一,高频 API 和配置如下:

  • new BrowserWindow(options):创建窗口,options 是窗口配置对象,核心配置如下:

    • width/height:窗口初始宽高。

    • title:窗口标题。

    • icon:窗口图标(不同系统格式不同,Windows 用 .ico,Mac 用 .icns)。

    • webPreferences:网页配置,核心是 preload、contextIsolation、nodeIntegration(安全相关)。

    • frame:是否显示窗口边框(false 为无边框窗口)。

    • resizable:是否允许窗口调整大小。

    • autoHideMenuBar:是否自动隐藏菜单栏(true 时,鼠标移到顶部显示)。

  • win.loadFile(path):加载本地 HTML 文件(渲染进程入口)。

  • win.loadURL(url):加载远程 URL(如 https://www.baidu.com)。

  • win.webContents.openDevTools():打开开发者工具(开发环境常用)。

  • win.setMenu(null):隐藏窗口菜单栏。

  • win.minimize()/win.maximize()/win.close():窗口最小化、最大化、关闭。

3. 进程间通信(IPC)API

主进程与渲染进程无法直接访问对方的资源,必须通过 IPC 机制通信,Electron 提供了两种核心通信方式:异步通信和同步通信,高频 API 如下:

  • 异步通信(推荐):主进程用 ipcMain,渲染进程用 ipcRenderer,通信双方无需等待对方响应,不阻塞进程。

    • ipcMain.on(channel, (event, data) => { ... }):主进程监听指定通道的消息。

    • ipcRenderer.send(channel, data):渲染进程向主进程发送消息。

    • event.reply(channel, data):主进程向发送消息的渲染进程回复消息。

  • 同步通信:渲染进程用 ipcRenderer.sendSync(channel, data),主进程用 ipcMain.on(channel, (event, data) => { event.returnValue = 响应数据; }),会阻塞渲染进程,不推荐频繁使用。

  • contextBridge:预加载脚本中使用,用于安全地将主进程的 API 暴露到渲染进程,避免直接暴露 ipcRenderer 带来的安全风险。

示例代码(IPC 异步通信):

  1. 预加载脚本(preload.js):暴露通信 API 给渲染进程
javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron');

// 安全暴露 API 到渲染进程的 window 对象
contextBridge.exposeInMainWorld('electronAPI', {
  // 渲染进程向主进程发送消息
  sendMessage: (channel, data) => ipcRenderer.send(channel, data),
  // 渲染进程监听主进程的回复
  onReply: (channel, callback) => ipcRenderer.on(channel, (event, data) => callback(data))
});
  1. 主进程(main.js):监听消息并回复
javascript 复制代码
const { ipcMain } = require('electron');

// 监听渲染进程发送的消息
ipcMain.on('message-from-renderer', (event, data) => {
  console.log('收到渲染进程消息:', data);
  // 向渲染进程回复消息
  event.reply('message-from-main', '已收到消息,感谢反馈!');
});
  1. 渲染进程(renderer.js):发送消息并监听回复
javascript 复制代码
// 调用预加载脚本暴露的 API
window.electronAPI.sendMessage('message-from-renderer', 'Hello Electron!');
// 监听主进程的回复
window.electronAPI.onReply('message-from-main', (data) => {
  console.log('收到主进程回复:', data);
});
4. 其他高频 API 模块
  • fs 模块(Node.js 原生):通过主进程访问本地文件系统,实现文件的读取、写入、删除等操作(渲染进程需通过 IPC 调用主进程的 fs 方法)。

  • dialog 模块:提供系统对话框(如打开文件、保存文件、提示框),替代浏览器的 alert、confirm 等方法,更贴近桌面应用体验。

  • tray 模块:创建系统托盘图标,支持右键菜单、点击事件,实现应用后台运行时的交互。

  • notification 模块:创建系统桌面通知,支持自定义标题、内容、图标,提升用户体验。

2.4 实战开发(从入门到部署,完整流程)

作为前端架构师,不仅要懂原理,还要能落地项目。本节将从环境搭建、Hello World 入门,到完整项目开发、打包部署,一步步实战,附详细代码和步骤,适配企业级项目开发规范。

2.4.1 环境搭建(前置依赖)

Electron 依赖 Node.js 运行时,需先安装 Node.js(建议 16+ 版本,与最新 Electron 版本兼容),具体步骤如下:

  1. 安装 Node.js:访问 Node.js 官网,下载 LTS 版本(如 18.17.0),安装后验证:
    node -v # 输出 v16+ 即可 npm -v # 输出 7+ 即可

  2. 配置 npm 镜像(国内用户推荐,加速依赖安装):
    npm config set registry https://registry.npm.taobao.org

  3. 安装 Electron:可全局安装(方便命令行调用),也可项目内局部安装(推荐,避免版本冲突):
    # 局部安装(推荐) npm install electron --save-dev

2.4.2 Hello World 入门(最小化应用)

创建一个最小化的 Electron 应用,熟悉主进程、渲染进程的基本结构,步骤如下:

  1. 创建项目目录,初始化 package.json:
    `# 1. 创建项目文件夹并进入
    mkdir electron-hello-world && cd electron-hello-world

2. 初始化 package.json(一路回车默认配置)

npm init -y

3. 安装 Electron

npm install electron --save-dev`

  1. 修改 package.json,配置主进程入口和启动脚本:
    { "name": "electron-hello-world", "version": "1.0.0", "main": "main.js", // 主进程入口文件 "scripts": { "start": "electron ." // 启动命令 }, "devDependencies": { "electron": "^40.0.0" // 安装的 Electron 版本 } }

  2. 创建主进程文件 main.js(核心逻辑):

    `const { app, BrowserWindow } = require('electron');

    const path = require('path');

// 避免重复创建窗口

let mainWindow;

// 创建窗口函数

function createWindow() {

mainWindow = new BrowserWindow({

width: 800,

height: 600,

title: "Electron Hello World",

webPreferences: {

preload: path.join(__dirname, 'preload.js'),

contextIsolation: true,

nodeIntegration: false

}

});

// 加载渲染进程页面(本地 HTML 文件)

mainWindow.loadFile('index.html');

// 开发环境打开开发者工具

if (process.env.NODE_ENV === 'development') {

mainWindow.webContents.openDevTools();

}

// 窗口关闭事件:释放窗口实例

mainWindow.on('closed', () => {

mainWindow = null;

});

}

// 应用就绪后创建窗口

app.whenReady().then(createWindow);

// 所有窗口关闭后退出应用(Windows/Linux)

app.on('window-all-closed', () => {

if (process.platform !== 'darwin') app.quit();

});

// Mac 系统激活应用时重新创建窗口

app.on('activate', () => {

if (BrowserWindow.getAllWindows().length === 0) createWindow();

});`

  1. 创建预加载脚本 preload.js:
    `const { contextBridge } = require('electron');

// 暴露基础 API 到渲染进程

contextBridge.exposeInMainWorld('electronAPI', {

appName: 'Electron Hello World',

version: '1.0.0'

});`

  1. 创建渲染进程页面 index.html(UI 界面):
    <!DOCTYPE html> Electron Hello WorldHello Electron!应用版本:

  2. 启动应用:npm start启动成功后,会弹出一个窗口,显示「Hello Electron!」和应用版本,这就是最小化的 Electron 应用。

2.4.3 实战项目:本地文件管理器(核心功能落地)

基于入门案例,开发一个简单的本地文件管理器,实现「打开文件夹、查看文件列表、查看文件内容」三大核心功能,贴近企业级项目开发规范,步骤如下:

1. 项目结构优化(企业级规范)
bash 复制代码
electron-file-manager/
├── src/
│   ├── main/          # 主进程代码
│   │   └── main.js    # 主进程入口
│   ├── renderer/      # 渲染进程代码
│   │   ├── index.html # 渲染页面
│   │   ├── css/       # 样式文件
│   │   │   └── index.css
│   │   └── js/        # 渲染逻辑
│   │       └── renderer.js
│   └── preload/       # 预加载脚本
│       └── preload.js
├── package.json       # 项目配置
└── .gitignore         # 忽略文件
2. 安装依赖(新增文件操作相关依赖)
bash 复制代码
# 安装 file-type 用于判断文件类型
npm install file-type --save
# 安装 @types/electron 用于 TypeScript 类型提示(可选)
npm install @types/electron --save-dev
3. 主进程开发(main.js):实现文件操作逻辑
javascript 复制代码
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const path = require('path');
const fs = require('fs').promises;
const { fileTypeFromFile } = require('file-type');

let mainWindow;

// 创建窗口
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 700,
    title: "Electron 文件管理器",
    webPreferences: {
      preload: path.join(__dirname, '../preload/preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  });

  // 加载渲染页面
  mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));

  // 开发环境打开开发者工具
  if (process.env.NODE_ENV === 'development') {
    mainWindow.webContents.openDevTools();
  }

  // 窗口关闭释放实例
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// IPC 通信:打开文件夹
ipcMain.on('open-folder', async (event) => {
  try {
    // 打开系统文件夹选择对话框
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ['openDirectory'] // 仅允许选择文件夹
    });

    // 用户取消选择
    if (result.canceled) return;

    const folderPath = result.filePaths[0];
    // 读取文件夹内的文件列表
    const files = await fs.readdir(folderPath, { withFileTypes: true });

    // 处理文件信息(名称、路径、类型、大小)
    const fileList = await Promise.all(
      files.map(async (file) => {
        const filePath = path.join(folderPath, file.name);
        const stats = await fs.stat(filePath);
        const fileType = file.isDirectory() ? 'directory' : await getFileType(filePath);
        return {
          name: file.name,
          path: filePath,
          type: fileType,
          size: stats.size,
          isDirectory: file.isDirectory(),
          mtime: stats.mtime.toLocaleString()
        };
      })
    );

    // 向渲染进程发送文件列表
    event.reply('file-list', { folderPath, fileList });
  } catch (error) {
    event.reply('file-error', error.message);
  }
});

// IPC 通信:查看文件内容
ipcMain.on('read-file', async (event, filePath) => {
  try {
    // 读取文件内容(仅支持文本文件)
    const content = await fs.readFile(filePath, 'utf8');
    event.reply('file-content', content);
  } catch (error) {
    event.reply('file-error', error.message);
  }
});

// 辅助函数:获取文件类型
async function getFileType(filePath) {
  const type = await fileTypeFromFile(filePath);
  return type ? type.mime : 'unknown';
}

// 应用生命周期监听
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
4. 预加载脚本(preload.js):暴露通信 API
javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron');

// 安全暴露 API 到渲染进程
contextBridge.exposeInMainWorld('fileManagerAPI', {
  // 打开文件夹
  openFolder: () => ipcRenderer.send('open-folder'),
  // 监听文件列表
  onFileList: (callback) => ipcRenderer.on('file-list', (event, data) => callback(data)),
  // 查看文件内容
  readFile: (filePath) => ipcRenderer.send('read-file', filePath),
  // 监听文件内容
  onFileContent: (callback) => ipcRenderer.on('file-content', (event, data) => callback(data)),
  // 监听错误信息
  onFileError: (callback) => ipcRenderer.on('file-error', (event, data) => callback(data))
});
5. 渲染进程开发(UI + 交互)
  1. index.css(样式文件):
css 复制代码
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Microsoft YaHei', Arial, sans-serif;
}

body {
  background-color: #f8f9fa;
  color: #333;
}

.header {
  padding: 15px 20px;
  background-color: #2c3e50;
  color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background-color: #3498db;
  color: white;
  cursor: pointer;
  transition: background-color 0.3s;
}

.btn:hover {
  background-color: #2980b9;
}

.container {
  display: flex;
  height: calc(100vh - 60px);
}

.file-list {
  width: 40%;
  border-right: 1px solid #ddd;
  padding: 20px;
  overflow-y: auto;
}

.file-content {
  width: 60%;
  padding: 20px;
  overflow-y: auto;
}

.folder-path {
  margin-bottom: 20px;
  font-size: 14px;
  color: #666;
}

.file-item {
  padding: 10px;
  border-radius: 4px;
  margin-bottom: 8px;
  cursor: pointer;
  transition: background-color 0.3s;
  display: flex;
  align-items: center;
}

.file-item:hover {
  background-color: #e3f2fd;
}

.file-item.directory {
  background-color: #f1f8fe;
}

.file-icon {
  margin-right: 10px;
  font-size: 18px;
}

.file-info {
  flex: 1;
}

.file-name {
  font-weight: 500;
}

.file-meta {
  font-size: 12px;
  color: #777;
}

.content-empty {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #999;
  font-size: 18px;
}

.content-text {
  white-space: pre-wrap;
  line-height: 1.5;
  font-size: 14px;
  color: #333;
}

.error {
  color: #e74c3c;
  margin-top: 10px;
  font-size: 14px;
}
  1. index.html(页面结构):
html 复制代码
<!DOCTYPE html>
Electron 文件管理器Electron 文件管理器未选择文件夹请选择一个文件查看内容
  1. renderer.js(交互逻辑):
javascript 复制代码
// 获取 DOM 元素
const openFolderBtn = document.getElementById('openFolderBtn');
const folderPathEl = document.getElementById('folderPath');
const fileListContainer = document.getElementById('fileListContainer');
const fileContentEl = document.getElementById('fileContent');
const errorMsgEl = document.getElementById('errorMsg');

// 打开文件夹按钮点击事件
openFolderBtn.addEventListener('click', () => {
  window.fileManagerAPI.openFolder();
});

// 监听文件列表
window.fileManagerAPI.onFileList(({ folderPath, fileList }) => {
  // 清空错误信息
  errorMsgEl.textContent = '';
  // 更新文件夹路径
  folderPathEl.textContent = folderPath;
  // 渲染文件列表
  renderFileList(fileList);
});

// 监听文件内容
window.fileManagerAPI.onFileContent((content) => {
  fileContentEl.innerHTML = `${content}`;
});

// 监听错误信息
window.fileManagerAPI.onFileError((error) => {
  errorMsgEl.textContent = `错误:${error}`;
});

// 渲染文件列表
function renderFileList(fileList) {
  fileListContainer.innerHTML = '';
  if (fileList.length === 0) {
    fileListContainer.innerHTML = '该文件夹为空';
    return;
  }

  fileList.forEach((file) => {
    const fileItem = document.createElement('div');
    fileItem.className = `file-item ${file.isDirectory ? 'directory' : ''}`;
    fileItem.innerHTML = `
      ${file.isDirectory ? '📂' : '📄'}${file.name}
          ${file.isDirectory ? '文件夹' : `类型:${file.type} | 大小:${formatSize(file.size)} | 修改时间:${file.mtime}`}
        
    `;

    // 点击文件/文件夹事件
    fileItem.addEventListener('click', () => {
      if (file.isDirectory) {
        // 文件夹:打开该文件夹(重新调用打开文件夹逻辑,简化处理)
        window.fileManagerAPI.openFolder();
      } else {
        // 文件:查看文件内容
        window.fileManagerAPI.readFile(file.path);
      }
    });

    fileListContainer.appendChild(fileItem);
  });
}

// 辅助函数:格式化文件大小(B -> KB -> MB)
function formatSize(size) {
  if (size < 1024) return `${size} B`;
  if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`;
  return `${(size / (1024 * 1024)).toFixed(2)} MB`;
}
4. 启动项目,测试功能
bash 复制代码
npm start

测试要点:点击「打开文件夹」选择任意文件夹,查看文件列表;点击文件查看内容,点击文件夹重新选择;测试错误场景(如无权限访问的文件夹),查看错误提示。

2.4.4 打包部署(企业级分发)

开发完成后,需要将应用打包为对应系统的可执行文件(.exe、.dmg、.deb),用于分发。Electron 常用的打包工具是 electron-builder(功能强大,支持多系统、自动签名、更新等),步骤如下:

  1. 安装 electron-builder:
    npm install electron-builder --save-dev

  2. 修改 package.json,添加打包脚本和配置:

(注:文档部分内容可能由 AI 生成)

相关推荐
全栈练习生2 小时前
封装数字滚动动画函数
前端
不爱吃炸鸡柳2 小时前
[特殊字符]C/C++内存管理深度解剖:从内存布局到new/delete底层,吃透面试必考核心
c语言·c++·面试
Lzh编程小栈2 小时前
数据结构与算法之队列深度解析:循环队列+C 语言硬核实现 + 面试考点全梳理
c语言·开发语言·汇编·数据结构·后端·算法·面试
TON_G-T2 小时前
useEffect为什么会触发死循环
java·服务器·前端
Aurorar0rua2 小时前
CS50 x 2024 Notes C - 02
前端
海参崴-3 小时前
C++代码格式规范
java·前端·c++
谢尔登3 小时前
【React】setState 触发渲染的流程
前端·react.js·前端框架
明灯伴古佛3 小时前
面试:什么是可重入性?为什么 synchronized 是可重入锁?
java·jvm·面试
摸鱼仙人~3 小时前
Vue中markdown-it基础使用教程
前端·javascript·vue.js