javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > Electron.js应用场景及案例

Electron.js核心详解、应用场景及完整案例

作者:行走の飞鱼

Electron.js是一个使用JavaScript、HTML和CSS开发跨平台桌面应用的Web框架,基于Chromium引擎,提供即时重载和内置调试工具,这篇文章主要介绍了Electron.js核心详解、应用场景及完整案例的相关资料,需要的朋友可以参考下

一、Electron.js 核心详解

1. 什么是 Electron.js?

Electron(原名为 Atom Shell)是由 GitHub 开发的开源框架,基于 Node.jsChromium,允许开发者使用 HTML、CSS、JavaScript 构建跨平台(Windows、macOS、Linux)的桌面应用程序。

核心优势:

2. 核心架构

Electron 应用由 主进程渲染进程 组成,通过 IPC(进程间通信)实现通信:

进程类型作用技术基础核心模块
主进程(Main Process)管理应用生命周期(启动/退出)、窗口创建、系统资源访问Node.js + Electron APIBrowserWindow(窗口)、app(应用)、Menu(菜单)、ipcMain(IPC通信)
渲染进程(Renderer Process)负责UI渲染,每个窗口对应一个独立渲染进程Chromium + Web 技术ipcRenderer(IPC通信)、remote(已废弃,改用 @electron/remote

关键原理

3. 核心模块速览

模块名核心功能
app应用生命周期管理(启动、退出、激活、事件监听)
BrowserWindow创建和控制应用窗口(大小、位置、样式、加载URL)
ipcMain/ipcRenderer主进程与渲染进程的异步通信
Menu/MenuItem创建应用菜单(顶部菜单、右键菜单)
Tray创建系统托盘图标和上下文菜单
dialog显示原生对话框(打开文件、保存文件、提示框)
fs(Node.js 模块)文件系统读写(主进程可直接使用,渲染进程需通过IPC)

二、Electron 应用场景

Electron 因跨平台、技术栈低门槛,被广泛用于以下场景:

1. 开发者工具

2. 生产力工具

3. 媒体/娱乐应用

4. 本地数据处理工具

5. 离线 Web 应用封装

三、完整案例:本地文件阅读器

功能说明

技术栈

步骤 1:项目初始化

1.1 创建项目目录

mkdir electron-file-reader
cd electron-file-reader

1.2 初始化 npm 项目

npm init -y

1.3 安装依赖

# 安装 Electron(生产依赖)
npm install electron --save
# 安装 iconv-lite(处理文件编码)
npm install iconv-lite --save

1.4 配置 package.json

修改 package.json,添加 Electron 启动脚本和主进程入口:

{
  "name": "electron-file-reader",
  "version": "1.0.0",
  "main": "main.js", // 主进程入口文件
  "scripts": {
    "start": "electron .", // 启动应用
    "package": "electron-packager . FileReader --platform=all --arch=all --out=dist" // 打包(需先安装 electron-packager)
  },
  "devDependencies": {},
  "dependencies": {
    "electron": "^28.0.0",
    "iconv-lite": "^0.6.3"
  }
}

步骤 2:编写主进程代码(main.js)

主进程负责窗口创建、文件读取、IPC通信:

const { app, BrowserWindow, dialog, ipcMain } = require('electron');
const fs = require('fs');
const path = require('path');
const iconv = require('iconv-lite');

let mainWindow;

// 创建主窗口
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 启用预加载脚本
      preload: path.join(__dirname, 'preload.js'),
      // 允许渲染进程使用 Node.js API(开发环境方便,生产环境建议禁用)
      nodeIntegration: false,
      contextIsolation: true // 启用上下文隔离,安全推荐
    }
  });

  // 加载前端页面
  mainWindow.loadFile('index.html');

  // 打开开发者工具(开发环境)
  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();
  }
});

// macOS 激活应用时重新创建窗口
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// IPC:监听渲染进程的"选择文件"请求
ipcMain.handle('select-file', async () => {
  // 打开文件选择对话框
  const result = await dialog.showOpenDialog(mainWindow, {
    title: '选择文本文件',
    filters: [
      { name: '文本文件', extensions: ['txt', 'md'] },
      { name: '所有文件', extensions: ['*'] }
    ],
    properties: ['openFile'] // 仅允许选择单个文件
  });

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

  // 返回选中的文件路径
  return result.filePaths[0];
});

// IPC:监听渲染进程的"读取文件"请求
ipcMain.handle('read-file', async (event, filePath, encoding) => {
  try {
    // 读取文件原始字节(避免编码问题)
    const buffer = fs.readFileSync(filePath);
    // 根据选择的编码解码
    const content = iconv.decode(buffer, encoding);
    return { success: true, content };
  } catch (error) {
    return { success: false, error: error.message };
  }
});

步骤 3:编写预加载脚本(preload.js)

预加载脚本在渲染进程加载前执行,用于暴露 IPC 通信接口(安全隔离):

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

// 向渲染进程暴露安全的 API(window.electron 全局对象)
contextBridge.exposeInMainWorld('electron', {
  // 选择文件
  selectFile: () => ipcRenderer.invoke('select-file'),
  // 读取文件
  readFile: (filePath, encoding) => ipcRenderer.invoke('read-file', filePath, encoding)
});

步骤 4:编写前端界面(index.html)

前端负责UI展示和用户交互,通过 window.electron 调用主进程API:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Electron 本地文件阅读器</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      background: #f5f5f5;
    }
    .header {
      display: flex;
      gap: 10px;
      margin-bottom: 20px;
    }
    button {
      padding: 8px 16px;
      cursor: pointer;
      background: #2f54eb;
      color: white;
      border: none;
      border-radius: 4px;
      font-size: 14px;
    }
    button:hover {
      background: #1d39c4;
    }
    select {
      padding: 8px;
      border-radius: 4px;
      border: 1px solid #ddd;
    }
    .file-path {
      margin: 10px 0;
      color: #666;
      font-size: 14px;
    }
    .content {
      width: 100%;
      height: calc(100vh - 120px);
      padding: 15px;
      border: 1px solid #ddd;
      border-radius: 4px;
      background: white;
      overflow: auto;
      white-space: pre-wrap; /* 保留换行和空格 */
      font-size: 14px;
      line-height: 1.6;
    }
    .error {
      color: #f5222d;
    }
  </style>
</head>
<body>
  <div class="header">
    <button id="selectBtn">选择文件</button>
    <select id="encodingSelect">
      <option value="utf8">UTF-8</option>
      <option value="gbk">GBK</option>
    </select>
  </div>
  <div class="file-path" id="filePath">未选择文件</div>
  <div class="content" id="content"></div>

  <script>
    // 获取DOM元素
    const selectBtn = document.getElementById('selectBtn');
    const encodingSelect = document.getElementById('encodingSelect');
    const filePathEl = document.getElementById('filePath');
    const contentEl = document.getElementById('content');

    // 选择文件按钮点击事件
    selectBtn.addEventListener('click', async () => {
      try {
        // 调用主进程的选择文件API
        const filePath = await window.electron.selectFile();
        if (!filePath) return;

        // 显示文件路径
        filePathEl.textContent = `当前文件:${filePath}`;
        contentEl.textContent = '正在读取文件...';

        // 获取选择的编码
        const encoding = encodingSelect.value;

        // 调用主进程的读取文件API
        const result = await window.electron.readFile(filePath, encoding);
        if (result.success) {
          contentEl.textContent = result.content;
          contentEl.classList.remove('error');
        } else {
          contentEl.textContent = `读取失败:${result.error}`;
          contentEl.classList.add('error');
        }
      } catch (error) {
        contentEl.textContent = `错误:${error.message}`;
        contentEl.classList.add('error');
      }
    });

    // 编码切换时重新读取文件
    encodingSelect.addEventListener('change', async () => {
      const filePath = filePathEl.textContent.replace('当前文件:', '');
      if (filePath === '未选择文件') return;

      contentEl.textContent = '正在重新读取文件...';
      const encoding = encodingSelect.value;
      const result = await window.electron.readFile(filePath, encoding);
      if (result.success) {
        contentEl.textContent = result.content;
        contentEl.classList.remove('error');
      } else {
        contentEl.textContent = `读取失败:${result.error}`;
        contentEl.classList.add('error');
      }
    });
  </script>
</body>
</html>

步骤 5:运行应用

在项目根目录执行以下命令启动应用:

npm start

步骤 6:打包应用(可选)

6.1 安装打包工具

npm install electron-packager --save-dev

6.2 执行打包命令

npm run package

打包完成后,会在 dist 目录下生成对应系统(Windows/macOS/Linux)的可执行文件。

案例效果

  1. 启动后显示"未选择文件",点击"选择文件"按钮可打开系统文件对话框
  2. 选择 .txt.md 文件后,自动读取并展示内容
  3. 可通过下拉框切换编码(解决GBK文件乱码问题)
  4. 支持窗口大小调整、最小化/关闭,内容区域自动滚动

四、关键注意事项

1. 安全性

2. 性能优化

3. 跨平台兼容性

4. 打包与分发

五、扩展方向

  1. 支持更多文件格式(如 PDF、Office 文件,需集成对应解析库)
  2. 添加文件编辑和保存功能
  3. 实现最近打开文件列表(通过 app.getPath('recentDocuments')
  4. 支持暗黑模式(通过 nativeTheme 模块)
  5. 集成云同步功能(通过 Node.js 调用云存储API)

到此这篇关于Electron.js核心详解、应用场景及完整案例的文章就介绍到这了,更多相关Electron.js应用场景及案例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文