Electron + Vue3 + TypeScript 项目快速搭建指南
基于 electron-vite-boilerplate | 在线演示: https://evite.netlify.app/
github地址:https://github.com/wuyongGitHub/electron-admin-template.git
技术栈
| 类别 | 选型 |
|---|---|
| 框架 | Electron |
| 前端 | Vue 3 |
| 构建 | Vite |
| 语言 | TypeScript |
| UI 库 | Element Plus |
| 状态管理 | Pinia |
| HTTP | Axios |
一、项目初始化
bash
npx degit alex8088/electron-vite-boilerplate electron-app
cd electron-app
npm install
npm run dev
如若无效直接进行git拉取
bash
git config --global --unset http.proxy
git config --global --unset https.proxy
git clone https://github.com/alex8088/electron-vite-boilerplate.git electron-admin-app

二、路由配置(二次封装)
安装
bash
npm install vue-router -S
目录结构
src/renderer/src/router/
├── index.ts # 入口,创建 router + 挂载守卫
├── routes.ts # 路由表
└── guards.ts # 导航守卫
为什么二次封装? 路由表 + 导航守卫混在一个文件里,项目大了难以维护。拆成三个职责单一的文件,各管各的。
router/index.ts
ts
import { createRouter, createWebHashHistory } from 'vue-router'
import { AppRoutes } from './routes'
import { beforeEachGuard, afterEachGuard } from './guards'
const router = createRouter({
history: createWebHashHistory(),
routes: AppRoutes,
})
router.beforeEach(beforeEachGuard)
router.afterEach(afterEachGuard)
export default router
router/routes.ts
ts
import type { RouteRecordRaw } from 'vue-router'
export const AppRoutes: RouteRecordRaw[] = [
{
path: '/',
name: 'layout',
component: () => import('@renderer/layout/index.vue'),
},
{
path: '/login',
name: 'login',
component: () => import('@renderer/views/login/Login.vue'),
meta: { title: '登录' },
},
]
router/guards.ts
ts
import type { Router } from 'vue-router'
export function beforeEachGuard(to: ReturnType<Router['resolve']>) {
// 全局前置守卫:权限校验、登录拦截等
}
export function afterEachGuard() {
// 全局后置守卫:页面标题更新、埋点等
}
main.ts 注册
ts
import router from './router'
app.use(router)
三、状态管理 Pinia
Pinia vs Vuex
| Vuex | Pinia | |
|---|---|---|
| mutations | 有 | 无(直接改 state) |
| modules | 有 | 无(天然拆分为多个 store) |
| TS 支持 | 一般 | 原生良好 |
| 体积 | 较大 | 轻量 |
安装
bash
npm install pinia pinia-plugin-persist -S
目录结构
src/renderer/src/store/
├── index.ts # 统一导出
├── useUserStore.ts # 用户模块
└── useAppStore.ts # 应用设置
store/index.ts
ts
export { useUserStore } from './useUserStore'
export { useAppStore } from './useAppStore'
store/useUserStore.ts
ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
rolePerm: [] as string[],
permissions: [] as string[],
}),
getters: {
isLoggedIn: (state) => !!state.token,
},
actions: {
setToken(token: string) {
this.token = token
},
},
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
paths: ['token', 'rolePerm', 'permissions'],
},
],
},
})
main.ts 注册
ts
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const pinia = createPinia()
pinia.use(piniaPluginPersist)
app.use(pinia)
四、路径别名
在 electron.vite.config.ts 的 renderer.resolve.alias 中配置:
ts
import { resolve } from 'path'
alias: {
'@renderer': resolve('src/renderer/src'),
'@views': resolve('src/renderer/src/views'),
'@router': resolve('src/renderer/src/router'),
'@store': resolve('src/renderer/src/store'),
'@utils': resolve('src/renderer/src/utils'),
'@api': resolve('src/renderer/src/api'),
'@layout': resolve('src/renderer/src/layout'),
}
五、HTTP 请求封装
安装 Axios
bash
npm install axios -S
代理配置
ts
server: {
proxy: {
'/api': {
target: 'http://uat.crm.xuexiluxian.cn',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
utils/request.ts
ts
import axios from 'axios'
import type { AxiosResponse } from 'axios'
const request = axios.create({
baseURL: '/api',
timeout: 10000,
})
// 请求拦截
request.interceptors.request.use(
(config) => {
// const user = useUserStore()
// if (user.token) config.headers.Authorization = `Bearer ${user.token}`
return config
},
(error) => Promise.reject(error)
)
// 响应拦截
request.interceptors.response.use(
(response: AxiosResponse) => {
const { code, data, message } = response.data
if (code === 200) return data
return Promise.reject(new Error(message || '请求失败'))
},
(error) => Promise.reject(error)
)
export default request
API 模块化
src/renderer/src/api/
├── login.ts
└── user.ts
ts
// api/login.ts
import request from '@utils/request'
interface LoginParams {
username: string
password: string
}
export function loginByJson(data: LoginParams) {
return request.post('/u/loginByJson', data)
}
六、Element Plus 按需引入
安装
bash
npm install element-plus -S
npm install unplugin-vue-components unplugin-auto-import -D
配置
ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
plugins: [
vue(),
AutoImport({ resolvers: [ElementPlusResolver()] }),
Components({ resolvers: [ElementPlusResolver()] }),
]
按需引入后,组件直接用无需手动 import,
ElMessage等 API 也会自动导入。
七、完整 electron.vite.config.ts
ts
import { resolve } from 'path'
import { defineConfig } from 'electron-vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
main: {},
preload: {},
renderer: {
resolve: {
alias: {
'@renderer': resolve('src/renderer/src'),
'@views': resolve('src/renderer/src/views'),
'@router': resolve('src/renderer/src/router'),
'@store': resolve('src/renderer/src/store'),
'@utils': resolve('src/renderer/src/utils'),
'@api': resolve('src/renderer/src/api'),
'@layout': resolve('src/renderer/src/layout'),
},
},
server: {
proxy: {
'/api': {
target: 'http://uat.crm.xuexiluxian.cn',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
plugins: [
vue(),
AutoImport({ resolvers: [ElementPlusResolver()] }),
Components({ resolvers: [ElementPlusResolver()] }),
],
},
})
八、项目结构总览
electron-app/
└── src/renderer/src/
├── main.ts # 入口
├── App.vue
├── api/ # 接口按模块
│ └── login.ts
├── router/ # 路由
│ ├── index.ts
│ ├── routes.ts
│ └── guards.ts
├── store/ # 状态管理
│ ├── index.ts
│ ├── useUserStore.ts
│ └── useAppStore.ts
├── utils/ # 工具函数
│ └── request.ts
├── views/ # 页面
└── layout/ # 布局
后续可补:i18n 多语言、深色模式、IPC 主/渲染进程通信、自动更新等。