如何在Electron中正确使用window.location.href实现路由跳转?
Electron 加载本地打包后的 React 资源默认使用 file:// 协议,直接赋值 window.location.href = '/login' 属于根路径跳转,在 file:// 协议下会直接解析为磁盘根路径下的 login 文件,也就是你看到的 C:///login 请求,自然找不到对应资源导致应用崩溃。Web 环境下 React 跑在 http/https 协议的服务上,根路径跳转默认相对于域名,所以可以正常运行。
方案1:使用 React Router 编程式导航(最推荐)
直接使用 React Router 提供的导航方法即可,内部会自动处理路由相对路径逻辑,天然兼容 Web 和 Electron 的 file 协议场景,不需要修改任何 Electron 配置,对原有 Web 逻辑无侵入。
React Router v6 示例代码:
import { useNavigate } from 'react-router-dom' function LogoutComponent() { const navigate = useNavigate() const handleLogout = () => { // 执行登出逻辑:清理token、用户缓存等 localStorage.clear() // 调用路由跳转方法,替代window.location操作 navigate('/login') } }
v5 版本使用 useHistory 的 push 方法即可,逻辑完全一致。
方案2:拼接完整跳转路径
如果你一定要使用 window.location 做跳转,需要判断运行环境补全路径前缀:
const isElectronEnv = window.navigator.userAgent.includes('Electron') const loginPath = isElectronEnv ? `${window.location.origin}/login` : '/login' window.location.href = loginPath
注意:该方案仅适配 Hash 路由,如果你用的是 Browser 路由,Electron 的 file 协议本身不支持 history 模式,需要额外配置
方案3:Electron 侧启动本地静态服务
如果你的项目有大量硬编码的根路径跳转逻辑,不想修改前端代码,可以在 Electron 主进程启动本地静态服务加载 React 打包产物,让 Electron 页面也跑在 http 协议下,和 Web 环境完全一致,原有跳转逻辑不需要修改即可生效。
主进程示例代码:
const { app, BrowserWindow } = require('electron') const express = require('express') const path = require('path') let mainWindow function createWindow() { // 启动静态服务加载React打包后的build目录 const expApp = express() expApp.use(express.static(path.join(__dirname, './build'))) // 随机占用可用端口 const server = expApp.listen(0, '127.0.0.1', () => { const port = server.address().port mainWindow.loadURL(`http://127.0.0.1:${port}`) }) mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true } }) } app.whenReady().then(createWindow)
该方案需要给 Electron 项目安装 express 依赖,打包时将 React 的 build 目录一起打进安装包即可。
- Browser 路由无法直接在 Electron 的 file 协议下运行,要么改用 Hash 路由,要么使用方案3启动本地 http 服务,要么在主进程做路由拦截重定向到 index.html。
- 不建议在 Electron 环境直接对
window.location赋值根路径,除非你明确当前协议和路径前缀。
内容的提问来源于stack exchange,提问作者heisenberg

