You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron学生备考APP:如何在index.html加载时调用JS函数?

解决Electron备考应用进度控制与按钮状态问题

核心问题分析

<body onload>在Electron渲染进程中可能因加载时序或框架机制失效,改用DOMContentLoaded事件能更可靠地监听DOM初始化完成时机,再读取进度变量控制按钮状态。

实现方案

方案1:本地存储进度(简单快速)

适合不需要严格防篡改的场景,用localStorage持久化进度变量:

HTML结构

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>备考应用</title>
</head>
<body>
  <button id="module1Btn">模块1:基础知识</button>
  <button id="module2Btn">模块2:考点强化</button>
  <button id="module3Btn">模块3:真题解析</button>
  <button id="module4Btn">模块4:技巧总结</button>
  <button id="testBtn">综合测试</button>

  <script src="./renderer.js"></script>
</body>
</html>

渲染进程逻辑(renderer.js)

// 监听DOM完全加载事件
document.addEventListener('DOMContentLoaded', () => {
  // 读取进度,默认0(首次启动)
  const progress = parseInt(localStorage.getItem('studyProgress')) || 0;
  
  // 绑定按钮状态更新
  updateButtonStates(progress);

  // 模块完成后的进度更新逻辑
  document.getElementById('module1Btn').addEventListener('click', () => {
    localStorage.setItem('studyProgress', '1');
    updateButtonStates(1);
  });

  document.getElementById('module2Btn').addEventListener('click', () => {
    localStorage.setItem('studyProgress', '2');
    updateButtonStates(2);
  });

  document.getElementById('module3Btn').addEventListener('click', () => {
    localStorage.setItem('studyProgress', '3');
    updateButtonStates(3);
  });

  document.getElementById('module4Btn').addEventListener('click', () => {
    localStorage.setItem('studyProgress', '4');
    updateButtonStates(4);
  });

  document.getElementById('testBtn').addEventListener('click', () => {
    localStorage.setItem('studyProgress', '5');
    updateButtonStates(5);
  });
});

// 统一管理按钮启用状态
function updateButtonStates(progress) {
  // 模块1完成后可禁用(可选,防止重复进入)
  document.getElementById('module1Btn').disabled = progress >= 1;
  // 后续模块需前序完成才能启用
  document.getElementById('module2Btn').disabled = progress < 1;
  document.getElementById('module3Btn').disabled = progress < 2;
  document.getElementById('module4Btn').disabled = progress < 3;
  document.getElementById('testBtn').disabled = progress < 4;
}

方案2:主进程托管进度(安全防篡改)

如果需要防止用户手动修改进度,将进度存储在主进程的文件中,通过IPC通信读取/更新:

主进程逻辑(main.js)

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

// 进度存储路径(Electron用户数据目录)
const progressFile = path.join(app.getPath('userData'), 'study-progress.json');

// 读取进度
function readProgress() {
  try {
    const data = fs.readFileSync(progressFile, 'utf8');
    return JSON.parse(data).progress || 0;
  } catch (err) {
    // 文件不存在或损坏,返回初始进度0
    return 0;
  }
}

// 保存进度
function writeProgress(progress) {
  fs.writeFileSync(progressFile, JSON.stringify({ progress }));
}

let mainWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), // 预加载脚本暴露API
      contextIsolation: true, // 启用上下文隔离,提升安全性
      nodeIntegration: false
    }
  });

  mainWindow.loadFile('index.html');

  // 响应渲染进程的进度读取请求
  ipcMain.handle('get-study-progress', () => readProgress());

  // 响应渲染进程的进度保存请求
  ipcMain.handle('save-study-progress', (_, progress) => {
    writeProgress(progress);
    return true;
  });
}

app.whenReady().then(createWindow);

预加载脚本(preload.js)

通过contextBridge安全暴露主进程API给渲染进程:

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

contextBridge.exposeInMainWorld('studyAPI', {
  getProgress: () => ipcRenderer.invoke('get-study-progress'),
  saveProgress: (progress) => ipcRenderer.invoke('save-study-progress', progress)
});

渲染进程逻辑修改(renderer.js)

document.addEventListener('DOMContentLoaded', async () => {
  // 从主进程异步读取进度
  const progress = await window.studyAPI.getProgress();
  
  updateButtonStates(progress);

  // 模块完成时调用主进程保存进度
  document.getElementById('module1Btn').addEventListener('click', async () => {
    await window.studyAPI.saveProgress(1);
    updateButtonStates(1);
  });

  // 其他按钮逻辑同理...
});

// 按钮状态更新函数和方案1一致
function updateButtonStates(progress) {
  document.getElementById('module1Btn').disabled = progress >= 1;
  document.getElementById('module2Btn').disabled = progress < 1;
  document.getElementById('module3Btn').disabled = progress < 2;
  document.getElementById('module4Btn').disabled = progress < 3;
  document.getElementById('testBtn').disabled = progress < 4;
}

关键注意事项

  • 避免直接启用nodeIntegration,用preload.js+contextBridge是Electron官方推荐的安全实践
  • 进度变量取值0-5,对应"未开始→模块1完成→模块2完成→模块3完成→模块4完成→测试完成"的状态

内容的提问来源于stack exchange,提问作者Mike M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:10:38