目录
[3.1 代码逐段解析](#3.1 代码逐段解析)
[3.1.1 模块导入与全局变量](#3.1.1 模块导入与全局变量)
[3.1.2 创建主窗口](#3.1.2 创建主窗口)
[3.1.3 开发模式与窗口事件](#3.1.3 开发模式与窗口事件)
[3.1.4 加载页面资源](#3.1.4 加载页面资源)
[3.1.5 应用就绪与生命周期管理](#3.1.5 应用就绪与生命周期管理)
一、项目介绍
**摘要:**本文带你快速上手一个基于 Electron + Vue3 仿 PC 微信客户端项目,涵盖无边框窗口、自定义标题栏、朋友圈等核心交互,并附源码解析与打包指南。
你是否想过,用前端技术也能打造出一款媲美原生体验的 PC 微信客户端?本项目正是这样一次尝试:它采用 无边框窗口 与 自定义标题栏 ,让界面更贴近微信原生的沉浸感;好友通讯录、聊天窗口、发送消息、设置管理乃至 朋友圈 等交互一应俱全,几乎复刻了 PC 微信的核心体验。
阅读本文,你将获得:快速上手 的完整步骤、源码解析 的关键实现思路,以及 打包指南,助你从零跑通并二次开发属于自己的桌面应用。
本项目源码下载地址:
源码下载
https://download.csdn.net/download/lucky_fang/93461822
项目使用electron+vue3+element-plus+vite+typescript+pinia+router等搭建,各种交互已经写好,参考PC微信客户端样式设计页面元素,包含登录窗口、好友通讯录、聊天记录、聊天窗口、发送消息、设置界面、朋友圈等,使用electron进行应用层实现和通讯,界面使用vue3和前端框架element-plus以及typescript来实现。
项目同时采用组件来布局整个框架,左侧+顶部+导航栏+具体页面功能展示容器。
electron官方文档:app | Electron
element-plus官方文档:Overview 组件总览 | Element Plus
二、项目结构
1.vscode项目截图:

2.项目依赖

三、项目截图
1.登录页
输入账密(admin/123456)登录,登录成功,跳转首页。

2.聊天主页
支持文本、图片样式

3.好友通讯录
好友列表+详情窗口


4.设置管理
账号与安全+通用+存储管理+关于




5.朋友圈

发表朋友圈

发表成功

四、源码解析
1.环境准备
确保你的电脑已安装 Node.js (建议 v18 LTS 或 v20 LTS) 和 npm 。
在 CMD 中输入以下命令检查版本:
node -v npm -v
2.使用脚手架创建项目
这是最标准、坑最少的方式。它将自动初始化 Electron、Vite、Vue3 和 TypeScript 的基础结构。
-
执行创建命令:
npm create electron-vite@latest my-electron-app注:
my-electron-app是你的项目名称,可以修改。 -
按照提示选择配置(在 CMD 中通过上下键选择,回车确认):
- Select a framework : 选择
vue - Select a variant : 选择
typescript - Package name: 直接回车(默认项目名称)
- Project description: 直接回车(可选)
- Select a framework : 选择
-
进入项目目录并安装依赖:
cd my-electron-app npm install -
启动开发服务器:
npm run dev此时,你应该能看到一个基本的 Electron 窗口,里面运行着 Vue3 页面。
当然了,如果您下载了本项目源码,就不需要执行以上过程来构建项目了,只需要关心以下命令即可:
1.安装依赖 npm install
2.启动项目 npm run dev 或 npm start
3.win打包 npm run build:win
4.mac打包 npm run build:mac
3.主配置文件源码
electron主文件,index.ts
javascript
import { app, shell, BrowserWindow, ipcMain, Menu} from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
let mainWindow: BrowserWindow | null = null
function createWindow(): void {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 900,
height: 670,
show: false,
frame: false,
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
}
})
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools()
// 可选:指定打开位置 'right' (默认), 'bottom', 'detach' (独立窗口)
// mainWindow.webContents.openDevTools({ mode: 'detach' })
}
mainWindow.on('ready-to-show', () => {
if (mainWindow) mainWindow.show()
})
mainWindow.on('closed', () => {
mainWindow = null
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
})
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
// Set app user model id for windows
electronApp.setAppUserModelId('com.electron')
// Default open or close DevTools by F12 in development
// and ignore CommandOrControl + R in production.
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
app.on('browser-window-created', (_, window) => {
optimizer.watchWindowShortcuts(window)
})
// IPC test
ipcMain.on('ping', () => console.log('pong'))
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
// IPC 处理:最小化
ipcMain.on('window-minimize', () => {
if (mainWindow) mainWindow.minimize()
})
// IPC 处理:关闭(隐藏到托盘或退出,这里简化为退出)
ipcMain.on('window-close', () => {
if (mainWindow) mainWindow.close()
})
// IPC 处理:打开外部链接
ipcMain.handle('open-external', async (_, url: string) => {
await shell.openExternal(url)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
3.1 代码逐段解析
下面按功能模块对主配置文件 index.ts 中的关键代码进行逐段拆解,帮助理解窗口创建、IPC 通信与生命周期管理的实现思路。
3.1.1 模块导入与全局变量
javascript
import { app, shell, BrowserWindow, ipcMain, Menu} from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
let mainWindow: BrowserWindow | null = null
这段代码从 electron 模块中导入应用生命周期管理(app)、系统外壳(shell)、窗口创建(BrowserWindow)、进程间通信(ipcMain)以及菜单(Menu)等核心 API。join 来自 path 模块,用于拼接跨平台的路径;electronApp、optimizer、is 来自 @electron-toolkit/utils,提供应用 ID 设置、快捷键优化和环境判断等工具方法。icon 通过 ?asset 后缀引入资源图片,用于 Linux 平台下的窗口图标。mainWindow 声明为可空的全局变量,用于在整个主进程中持有主窗口引用,方便后续对窗口进行最小化、关闭等操作。
3.1.2 创建主窗口
javascript
function createWindow(): void {
mainWindow = new BrowserWindow({
width: 900,
height: 670,
show: false,
frame: false,
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
}
})
createWindow 函数负责创建应用的主窗口。width 和 height 指定窗口尺寸为 900×670,与仿 PC 微信客户端的界面比例保持一致。show 设为 false 表示窗口先不显示,等待页面渲染完成后再展示,避免白屏闪烁。frame 设为 false 去掉系统默认边框,配合自定义标题栏实现无边框窗口效果,这也是仿微信界面常见的做法。autoHideMenuBar 自动隐藏默认菜单栏。在 Linux 平台下通过展开运算符附加 icon 配置。webPreferences 中 preload 指向预加载脚本,用于在渲染进程与主进程之间建立安全的桥接通道;sandbox 设为 false 允许预加载脚本使用完整的 Node.js 能力。
3.1.3 开发模式与窗口事件
javascript
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools()
}
mainWindow.on('ready-to-show', () => {
if (mainWindow) mainWindow.show()
})
mainWindow.on('closed', () => {
mainWindow = null
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
})
开发环境下自动打开开发者工具,方便调试页面。ready-to-show 事件在页面首次渲染完成后触发,此时调用 show 显示窗口,确保用户看到的是完整页面而非加载过程。closed 事件在窗口关闭时将 mainWindow 置为 null,避免引用已销毁的窗口对象。setWindowOpenHandler 拦截渲染进程中所有新窗口打开请求,统一交给系统默认浏览器通过 shell.openExternal 处理,并返回 deny 阻止在应用内创建新窗口,这是 Electron 应用的安全最佳实践。
3.1.4 加载页面资源
javascript
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
}
这里根据运行环境选择加载方式:开发模式下从 electron-vite 启动的本地开发服务器地址加载页面,支持热更新(HMR),修改渲染进程代码后页面自动刷新;生产模式下则加载打包后的本地 HTML 文件。这种双分支策略是 electron-vite 脚手架的标准写法,兼顾开发体验与发布效率。
3.1.5 应用就绪与生命周期管理
javascript
app.whenReady().then(() => {
electronApp.setAppUserModelId('com.electron')
app.on('browser-window-created', (_, window) => {
optimizer.watchWindowShortcuts(window)
})
ipcMain.on('ping', () => console.log('pong'))
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})|DSML|
app.whenReady() 是 Electron 应用启动的入口,只有在该 Promise 完成后才能创建窗口或使用部分系统 API。setAppUserModelId 为 Windows 平台设置应用用户模型 ID,用于任务栏分组和通知展示。browser-window-created 事件配合 optimizer.watchWindowShortcuts 实现开发环境 F12 开关开发者工具、生产环境屏蔽刷新快捷键等优化。ipcMain.on('ping') 是一个简单的 IPC 测试通道,用于验证主进程与渲染进程的通信是否正常。activate 事件是 macOS 特有的处理逻辑:当点击 Dock 图标且没有其他窗口打开时,重新创建主窗口,符合 macOS 应用的使用习惯。
3.1.6 窗口全部关闭与退出策略
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})|DSML|
window-all-closed 事件在所有窗口关闭后触发。这里做了平台差异化处理:在 macOS 上应用通常保持运行,等待用户通过 Cmd + Q 显式退出;在其他平台(Windows、Linux)上则直接调用 app.quit() 结束进程,释放系统资源。这是 Electron 官方推荐的生命周期管理方式。
3.1.7 IPC 通信:窗口控制与外部链接
ipcMain.on('window-minimize', () => {
if (mainWindow) mainWindow.minimize()
})
ipcMain.on('window-close', () => {
if (mainWindow) mainWindow.close()
})
ipcMain.handle('open-external', async (_, url: string) => {
await shell.openExternal(url)
})|DSML|
这三段代码定义了主进程对外提供的 IPC 接口。window-minimize 和 window-close 分别监听渲染进程发来的最小化、关闭请求,通过 mainWindow 引用调用对应方法,实现无边框窗口的自定义标题栏按钮功能。open-external 使用 ipcMain.handle 注册异步处理函数,接收渲染进程传来的 URL 并调用 shell.openExternal 在系统浏览器中打开,用于处理「查看源码」「访问官网」等外部跳转需求。整体设计思路是:渲染进程不直接操作窗口或系统能力,而是通过 IPC 向主进程发送请求,由主进程统一执行,既保证了功能完整,又遵循了 Electron 的安全隔离原则。
4.项目依赖
package.json
javascript
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "An Electron application with Vue and TypeScript",
"main": "./out/main/index.js",
"author": "example.com",
"homepage": "https://electron-vite.org",
"scripts": {
"format": "prettier --write .",
"lint": "eslint --cache .",
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
"typecheck": "npm run typecheck:node && npm run typecheck:web",
"start": "electron-vite preview",
"dev": "electron-vite dev",
"build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
"build:mac": "npm run build && electron-builder --mac",
"build:linux": "npm run build && electron-builder --linux"
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/utils": "^4.0.0",
"@element-plus/icons-vue": "^2.3.2",
"dayjs": "^1.11.10",
"element-plus": "^2.6.1",
"pinia": "^2.1.7",
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"pinyin-pro": "^3.18.0"
},
"devDependencies": {
"@electron-toolkit/eslint-config-prettier": "3.0.0",
"@electron-toolkit/eslint-config-ts": "^3.1.0",
"@electron-toolkit/tsconfig": "^2.0.0",
"@types/node": "^22.19.1",
"@vitejs/plugin-vue": "^6.0.2",
"electron": "^39.2.6",
"electron-builder": "^26.0.12",
"electron-vite": "^5.0.0",
"eslint": "^9.39.1",
"eslint-plugin-vue": "^10.6.2",
"prettier": "^3.7.4",
"typescript": "^5.9.3",
"vite": "^7.2.6",
"vite-plugin-electron": "^0.28.4",
"vite-plugin-electron-renderer": "^0.14.5",
"vue": "^3.5.25",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.1.6"
}
}
五、总结
项目页面完整,后续可能将不断升级,完善其他页面。
关注作者,及时了解更多好项目!
更多优质项目请看作者主页!
获取源码或如需帮助,可通过博客后面名片+作者即可!
源码下载
https://download.csdn.net/download/lucky_fang/93461822
其他作品集合
- 《vue+element实现电商商城礼品代发网,商品、订单管理》
- 《vue+vant2完美实现香奈儿移动端商城网站》
- 《vue+elementui实现联想购物商城,样式美观大方》
- 《vue+elementui实现英雄联盟道具城》
- 《vue+elementui实现app布局小米商城,样式美观大方,功能完整》
- 《vue完美模拟pc版快手,实现短视频,含短视频详情播放》
- 《vue+element实现蔬菜、水果、电商商城》
- 《vue实现美观大方的动漫、cos、帖子类型网站》
- 《vue实现好看的相册、图片网站》
- 《高度仿PC版《微信读书》,好看的小说、读书网站》
- 《vue+element实现非常好看的鲜花网站商城,页面完整,样式美观》
- 《vue+elementui+springboot前后端分离实现通用商城管理后台》
- 《微信小程序日记、微信小程序个人空间、个人日记》
- 《vue+element模仿腾讯视频电影网站》
- 《vue+element高度仿照QQ音乐,完美实现PC端QQ音乐》
- 《vue+element详细完整实现个人博客、个人网站》
- 《vue+elementui+springboot前后端分离实现学校帖子网站,学校大作业》
- 《vue+elementui实现U袋网-完整版》
- 《vue+element+electron仿微信实现》
- 《vue+element模仿电商商城,前后端分离实现,下单微信扫码支付》
- 《electron+vue+elementui实现类似QQ窗口靠边自动边缘隐藏》
- 《微信小程序仿唯聚时代,微信小程序商城》
- 《jquery+bootstrap完整丰富样式开发框架源码,各种现成样式简单易用》
- 《html+css响应式旅游主题网站模板,旅游网站,企业文化新闻类网站》
- 《css+html各种动态、动画、3D相册等7件套》
- 《仿华为电商商城,官网,华为超级新品日demo,大屏霸气且简洁》
- 《vue+element简单实现商城网站首页,模仿电商商城》
- 《vue+elementui实现非常好看的博客、网站首页,网站模板》
- 《elementui+vue实现经典管理系统布局框架,拿来即用》
- 《简系统登录页模板html+vue+elementui》
- 《vue+elementui完美实现博客、网站、个人网站,高仿"张凯博客"》
- 《vue+elementui完美实现后台管理系统的左、右、顶部菜单布局》
- 《html5+css3实现3D正方体动画相册2种+3D旋转木马立体动画相册+表白文字加动画爱心+炫酷万花筒五件套含音乐》
- 《后端使用springboot+maven+shiro+mybatis+mysql,前端使用H-ui.admin_v3.1.3.1,快速实现管理后台功能》
- 《springboot+thymeleaf+maven+html+css实现精美大方好看官网模板完整源码》
- 《html+css实现好友列表,类似QQ群聊成员列表》