Vue3 + Vite + Element Plus web转为 Electron 应用,解决无法登录、隐藏自定义导航栏

如何在vue3 + Vite + Element Plus搭好的架构下转为 electron应用呢?

https://www.electronjs.org/zh/docs/latest/官方文档 https://www.electronjs.org/zh/docs/latest/

第一步:安装 electron相关依赖

npm install electron electron-builder concurrently cross-env --save-dev

本来想学习electron框架 web如何转 electron框架做个桌面应用,结果卡在了安装依赖有点无语。。。一开始以为是npm安装太慢卡死,然后尝试用淘宝镜像cnpm安装、npm版本升级等等一顿操作,最后是安装成功了,但是npm list electron查看版本信息各种兼容报。。

怀疑是electron版本37.2.6版本太高了,把electron降到22还是各种报错。。。

解决修改镜像源:

npm config edit //打开npm配置文件

在配置文件中添加

electron_mirror=https://cdn.npmmirror.com/binaries/electron/

electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

添加完成后执行安装命令 :

npm install electron electron-builder concurrently cross-env --save-dev

各种踩坑后总算是安装成功了~

第二步:配置 Electron 主进程

创建 electron文件夹

创建:main.js

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

let mainWindow

function createWindow() {
   
  mainWindow = new BrowserWindow({ 
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  })
  
  //创建空菜单 - 菜单栏隐藏但快捷键可用
  const emptyMenu = Menu.buildFromTemplate([])
  Menu.setApplicationMenu(emptyMenu)


   // 修改生产环境加载逻辑
if (process.env.NODE_ENV === 'development') {
  mainWindow.loadURL('http://localhost:8888') //确保自己的端口一致,不然运行调试或打包无效
} else {
  // 确保正确加载打包后的文件
  const indexPath = path.join(__dirname, '../dist/index.html')
  mainWindow.loadFile(indexPath).catch(err => {
    console.error('加载失败:', err)
    // 备用加载方式
    mainWindow.loadURL(`file://${indexPath}#/`)
  })
}

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


// 处理渲染进程的快捷键事件
ipcMain.on('reload-app', () => {
  mainWindow.reload()
})

ipcMain.on('toggle-devtools', () => {
  mainWindow.webContents.toggleDevTools()
})

ipcMain.on('force-reload', () => {
  mainWindow.webContents.reloadIgnoringCache()
})

app.on('ready', createWindow)

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

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})

创建:preload.js

javascript 复制代码
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('electron', {
  
})

第三步:修改package.json

javascript 复制代码
{
  "name": "my-vue-electron-app",
  "private": true,
  "version": "0.0.1",
  "main": "electron/main.js",
  "scripts": {
    "dev": "concurrently -k \"cross-env NODE_ENV=development vite\" \"cross-env NODE_ENV=development electron .\"",
    "build": "vite build && electron-builder",
    "preview": "vite preview",
    "electron:serve": "electron ."
  },
  "build": {
    "appId": "com.example.myvueelectronapp",
    "productName": "你的管理平台",
    "directories": {
      "output": "build"
    },
    "files": [
      "dist/**/*",
      "electron/**/*",
      "!node_modules/**/*"
    ],
    "win": {
      "target": "nsis",
	    "icon": "public/02.ico"
    },
    "mac": {
      "target": "dmg",
      "icon": ""
    },
    "linux": {
      "target": "AppImage",
      "icon": ""
    }
  },

注意图标icon格式和规范大小,npm run dev,调试不会影响但是打包会提示报错

第四步:修改 Vite 配置

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
    base: './',
	server: {
		open: true,
		host: "0.0.0.0",
		https: false,
		//端口号
		port: 8082,
		hmr: true,
		proxy: {
			'/api': {
				target: '0', 
				ws: true,
				changeOrigin: true,
				rewrite: (path) => path.replace(/^\/api/, ''),
			},
		},
	},
    build: {
     outDir: 'dist',
 	 emptyOutDir: true,
   }
})

第五步: npm run dev 调试

第六步: 打包electron npm run build

完成打包后双击打开调试版本与.exe应用

发现登录后路由无法跳转了,原因是Cookies在桌面无效;我项目toke是存在Cookies里面,造成登录路由无法跳转。。。

解决把存储在Cookies数据存储改成 localStorage或sessionStorage 然后重新登录就ok

第七步:隐藏或重置操作导航栏 https://www.electronjs.org/zh/docs/latest/tutorial/custom-title-bar

1.隐藏导航栏,保留调试效果:

修改main.js

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

let mainWindow

function createWindow() {
   
  mainWindow = new BrowserWindow({ 
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  })
  
  //创建空菜单 - 菜单栏隐藏但快捷键可用
  const emptyMenu = Menu.buildFromTemplate([])
  Menu.setApplicationMenu(emptyMenu)


   // 修改生产环境加载逻辑
if (process.env.NODE_ENV === 'development') {
  mainWindow.loadURL('http://localhost:8888')
} else {
  // 确保正确加载打包后的文件
  const indexPath = path.join(__dirname, '../dist/index.html')
  mainWindow.loadFile(indexPath).catch(err => {
    console.error('加载失败:', err)
    // 备用加载方式
    mainWindow.loadURL(`file://${indexPath}#/`)
  })
}

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


// 处理渲染进程的快捷键事件
ipcMain.on('reload-app', () => {
  mainWindow.reload()
})

ipcMain.on('toggle-devtools', () => {
  mainWindow.webContents.toggleDevTools()
})

ipcMain.on('force-reload', () => {
  mainWindow.webContents.reloadIgnoringCache()
})

app.on('ready', createWindow)

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

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})

修改preload.js

javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron')

// 安全地暴露 API 给渲染进程
contextBridge.exposeInMainWorld('electron', {
  // 可以在这里添加需要暴露的 API
})

// 监听键盘事件
document.addEventListener('keydown', (event) => {
  // Ctrl/Cmd + R: 刷新
  if ((event.ctrlKey || event.metaKey) && event.key === 'r') {
    event.preventDefault()
    ipcRenderer.send('reload-app')
  }
  
  // F12: 开发者工具
  if (event.key === 'F12') {
    event.preventDefault()
    ipcRenderer.send('toggle-devtools')
  }
  
  // Ctrl/Cmd + Shift + R: 强制刷新
  if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'R') {
    event.preventDefault()
    ipcRenderer.send('force-reload')
  }
})

成功去掉导航栏,快捷键也可调试

2.自定义导航栏名称:

修改main.js

javascript 复制代码
//创建空菜单 命名可根据需求修改
  const template = [
    {
      label: 'File',
      submenu: [
        { role: 'quit' }
      ]
    },
    {
      label: 'Edit',
      submenu: [
        { role: 'undo' },
        { role: 'redo' },
        { type: 'separator' },
        { role: 'cut' },
        { role: 'copy' },
        { role: 'paste' }
      ]
    },
    {
      label: 'View',
      submenu: [
        { role: 'reload' },
        { role: 'forcereload' },
        { role: 'toggledevtools' },
        { type: 'separator' },
        { role: 'resetzoom' },
        { role: 'zoomin' },
        { role: 'zoomout' },
        { type: 'separator' },
        { role: 'togglefullscreen' }
      ]
    }
  ]
  const emptyMenu = Menu.buildFromTemplate(template)
  Menu.setApplicationMenu(emptyMenu)

修改preload.js

javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
 
})

// 监听键盘事件
// document.addEventListener('keydown', (event) => {
  // Ctrl/Cmd + R: 刷新
  // if ((event.ctrlKey || event.metaKey) && event.key === 'r') {
  //   event.preventDefault()
  //   ipcRenderer.send('reload-app')
  // }
  
  // // F12: 开发者工具
  // if (event.key === 'F12') {
  //   event.preventDefault()
  //   ipcRenderer.send('toggle-devtools')
  // }
  
  // // Ctrl/Cmd + Shift + R: 强制刷新
  // if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'R') {
  //   event.preventDefault()
  //   ipcRenderer.send('force-reload')
  // }
// })
相关推荐
PYB311 小时前
【Web·JS·基础】函数的使用和展运算符...objs
前端·javascript
GuoguoDad~11 小时前
用 WorkBuddy 写了个 ImageKit 上传工具
electron·reactjs
默_笙12 小时前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
变与不变80613 小时前
js同步和异步难点重点详解
开发语言·javascript·ecmascript
Dovis(誓平步青云)14 小时前
多个链接不等于多份证据,新闻核验看板怎样合并来源
java·服务器·前端·javascript·人工智能·pdf·电脑
Dovis(誓平步青云)14 小时前
几个方案来回选不定?做一个随时切换的候选推荐页
android·java·服务器·开发语言·javascript·数据库·智能化
可乐鸡翅yeah_16 小时前
fmp4 碎片 MP4 格式 HLS 流,和传统 TS 分片有什么不一样
开发语言·javascript·ios·音视频·safari·m3u8·m3u8在线播放
ss27317 小时前
AI全栈实战 | 2.3-01 组件库实战:Element Plus 怎么搭出专业界面,过度封装为什么成维护负担
前端·javascript·elementui·vue
福兮说17 小时前
URL 编码的七个坑:c++ 传到后端变空格、%25 套娃、截断 emoji 直接报错
开发语言·前端·javascript·node.js·url
小的时候可菜了17 小时前
JS 异步的本质:从单线程到 thenable(一条进化链)
开发语言·前端·javascript