You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何修改Electron应用启动及无网络状态下的加载界面?

修改Electron应用的加载界面(启动+无网络场景)

作为Electron开发的老玩家,我来一步步教你搞定这两个场景的加载界面自定义——不管是启动时的闪屏,还是无网络时的提示界面,都能轻松拿捏。

一、自定义启动时的加载闪屏

Electron本身没有默认的启动加载界面,我们可以通过创建一个临时的"闪屏窗口"来实现完全自定义的效果,步骤很清晰:

  1. 写好你的闪屏界面文件
    新建一个splash.html,把你想要的加载样式、动画、logo都放进去,比如这样:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>加载中...</title>
    <style>
        body {
            margin: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #2c3e50;
            color: white;
        }
        .loader {
            width: 50px;
            height: 50px;
            border: 5px solid #f3f3f3;
            border-top: 5px solid #3498db;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <div class="loader"></div>
    <p>正在启动应用,请稍候...</p>
</body>
</html>
  1. 在主进程控制闪屏的生命周期
    打开你的主进程文件(比如main.js),先启动闪屏窗口,等主窗口完全加载完成后再关闭它:
const { app, BrowserWindow } = require('electron');
const path = require('path');

let mainWindow;
let splashWindow;

// 创建闪屏窗口
function createSplashWindow() {
    splashWindow = new BrowserWindow({
        width: 400,
        height: 300,
        frame: false, // 去掉窗口边框,做无边框闪屏
        transparent: true, // 可选:设置透明背景,更美观
        alwaysOnTop: true,
        webPreferences: {
            nodeIntegration: false, // 安全建议:禁用node集成
            contextIsolation: true
        }
    });

    splashWindow.loadFile(path.join(__dirname, 'splash.html'));

    // 窗口关闭时清空引用
    splashWindow.on('closed', () => {
        splashWindow = null;
    });
}

// 创建主窗口
function createMainWindow() {
    mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        show: false, // 先隐藏主窗口,等加载完成再显示
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true
        }
    });

    mainWindow.loadFile(path.join(__dirname, 'index.html'));

    // 主窗口完全加载后,显示主窗口并关闭闪屏
    mainWindow.on('ready-to-show', () => {
        mainWindow.show();
        if (splashWindow) splashWindow.close();
    });

    mainWindow.on('closed', () => {
        mainWindow = null;
    });
}

// 应用就绪后启动两个窗口
app.whenReady().then(() => {
    createSplashWindow();
    createMainWindow();

    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
            createSplashWindow();
            createMainWindow();
        }
    });
});

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
});

这里的核心是ready-to-show事件——它会在主窗口的内容完全渲染好之后触发,这时候关闭闪屏、显示主窗口,用户体验会很流畅。

二、无网络状态下的加载/错误界面

这个场景分两种情况:启动时就没网,以及运行过程中突然断网,我们都要处理到:

1. 渲染进程直接检测(简单高效)

在你的主界面index.html里,直接用浏览器原生的navigator.onLineAPI来检测网络状态,切换显示内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>我的Electron应用</title>
    <style>
        #app-content { display: none; }
        #offline-screen {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #e74c3c;
            color: white;
        }
        .retry-btn {
            padding: 10px 20px;
            margin-top: 20px;
            background: white;
            color: #e74c3c;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <!-- 无网络时显示的界面 -->
    <div id="offline-screen">
        <h2>网络连接失败</h2>
        <p>请检查你的网络连接后重试</p>
        <button class="retry-btn" onclick="checkNetwork()">重试连接</button>
    </div>

    <!-- 正常应用内容 -->
    <div id="app-content">
        <h1>应用主界面</h1>
        <!-- 你的应用内容 -->
    </div>

    <script>
        // 检查网络状态并切换界面
        function checkNetwork() {
            if (navigator.onLine) {
                document.getElementById('offline-screen').style.display = 'none';
                document.getElementById('app-content').style.display = 'block';
                // 这里可以重新加载远程数据或资源
            }
        }

        // 页面加载时初始化检测
        window.addEventListener('load', () => {
            checkNetwork();
        });

        // 监听网络状态变化(在线/离线)
        window.addEventListener('online', checkNetwork);
        window.addEventListener('offline', () => {
            document.getElementById('offline-screen').style.display = 'flex';
            document.getElementById('app-content').style.display = 'none';
        });
    </script>
</body>
</html>

这种方式不需要主进程参与,直接在渲染层搞定,简单又高效。

2. 主进程检测网络(进阶场景)

如果需要在主进程层面统一控制网络状态(比如多个窗口共享状态),可以用Electron的net模块来检测,再通过IPC通知渲染进程:

主进程代码片段:

const { net } = require('electron');

// 检测网络连通性的函数
function checkInternetConnection() {
    return new Promise((resolve) => {
        // 可以换成国内可靠的地址,比如百度
        const request = net.request('https://www.google.com');
        request.on('response', () => resolve(true));
        request.on('error', () => resolve(false));
        request.end();
    });
}

// 应用启动时检测网络,通知渲染进程
app.whenReady().then(async () => {
    const isOnline = await checkInternetConnection();
    if (mainWindow) {
        mainWindow.webContents.send('network-status', isOnline);
    }
});

渲染进程监听IPC:

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

ipcRenderer.on('network-status', (event, isOnline) => {
    if (isOnline) {
        document.getElementById('offline-screen').style.display = 'none';
        document.getElementById('app-content').style.display = 'block';
    } else {
        document.getElementById('offline-screen').style.display = 'flex';
        document.getElementById('app-content').style.display = 'none';
    }
});

三、一些实用小技巧

  • 闪屏窗口建议开启transparent: true,但要注意Windows平台可能需要额外配置(比如在package.json里加"build": {"win": {"transparent": true}})。
  • 网络检测不要只依赖一个地址,最好多选几个可靠的域名,避免因为单一地址故障导致误判。
  • 如果你的应用有缓存数据,无网络时可以优先显示缓存内容,再加上无网络提示,用户体验会更好。

内容的提问来源于stack exchange,提问作者Dhairya

火山引擎 最新活动