明廷盛 嘻嘻😁

第一章 快速上手

第一节 Electron 下载

STEP1: 下载Electron脚手架

官网: https://evite.netlify.app/ (拖到最下面就是这个)

npx degit alex8088/electron-vite-boilerplate electron-app
cd electron-app

npm install
npm run dev

STEP2: 修改如下文件

目的是删除 TS 的检测和格式校验

  1. 删除 ①eslintrc.cjs.eslintignore.prettierrc.yaml.prettierignore
  2. 更新包:
npm install --package-lock-only
  1. 然后复制替换如下文件📃
{
"name": "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": {
"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.0",
"@electron-toolkit/utils": "^3.0.0",
"vue-router": "^5.0.6"
},
"devDependencies": {
"@electron-toolkit/tsconfig": "^1.0.1",
"@types/node": "^18.19.9",
"@vitejs/plugin-vue": "^5.0.3",
"electron": "^28.2.0",
"electron-builder": "^24.9.1",
"electron-vite": "^2.0.0",
"typescript": "^5.3.3",
"vite": "^5.0.12",
"vue": "^3.4.15",
"vue-tsc": "^1.8.27"
}
}
  • 删除空!
{}
{
"recommendations": []
}

第二节 Router

STEP1: 安装路由

vue默认都是, 在 \electron-app\src\renderer\src\这个src目录下进行的

STEP1: 安装vue-router: npm install vue-router -S
STEP2: 新建router/index.ts

import { createRouter, createWebHashHistory } from "vue-router";

const router = createRouter({
history: createWebHashHistory(),//hash模式
routes: [//路由配置规则数组
{ path: "/test", name: "测试", component: () => import("../views/TestPanelView.vue") },
],
});

// 1.前置路由守卫
router.beforeEach((to, from) => {
console.log("前置路由守卫", to, from);
return true; // 放行 for test
});

// 2.后置路由守卫
router.afterEach((to, from) => {
console.log("后置路由守卫", to, from);
});

export default router;
  • main.ts中use一下router
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'; // 路由

const app = createApp(App);
app.use(router); // 1.使用路由

app.mount('#app');

需求: 点击按钮跳转到TestPanelView面板

image.png|475
  1. App.vue
<script setup lang="ts">
import router from './router'

const ipcHandle = () => window.electron.ipcRenderer.send('ping')
const goTestPanel = () => router.push('/test') // 点击按钮跳转TestPanelView面板

</script>

<template>
<button @click="goTestPanel">Go TestPanel</button>
<router-view></router-view>
</template>
  1. views/TestPanelView.vue
<script setup lang="ts">

</script>

<template>
<h1>TestPanel</h1>
</template>

<style scoped></style>

STEP2: 路由二次封装

  • 疑问: 为什么路由二次封装?
  • 解答: router文件中在写项目中包含:路由表、导航守卫等等内容,假设路由表特别多 或 导航守卫内容特别多,代码则很难维护和阅读,所以二次封装路由是为了方便后期维护和管理。
  • 具体怎么做: ①把路由表分一个文件router/routes ②把路由守卫分一个文件router/guards
    image.png|1

主路由

import { createRouter, createWebHashHistory } from "vue-router";
import { AppRoutes } from './routes'
import { beforeEach, afterEach } from './guards'

const router = createRouter({
history: createWebHashHistory(),//hash模式
routes: AppRoutes, // 路由表
});

//注册路由守卫
router.beforeEach(beforeEach);
router.afterEach(afterEach);


export default router;

路由表

export const AppRoutes = [//路由配置规则数组
{ path: "/test", name: "测试", component: () => import("../views/TestPanelView.vue") },
]

导航守卫

// 1.前置路由守卫
export const beforeEach = async (to, from) => {
console.log("前置路由守卫", to, from);
return true; // 放行 for test
};

// 2.后置路由守卫
export const afterEach = (to, from) => {
console.log("后置路由守卫", to, from);
};

第三节 Pinia

STEP1: 安装pinia

image.png|500

STEP1: npm install pinia -S
STEP2: main.ts中引入

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'; // 路由
import { createPinia } from 'pinia';

const app = createApp(App);
app.use(router); // 1.使用路由
app.use(createPinia()); // 2.使用pinia状态管理

app.mount('#app');

  • store/index.ts
import { defineStore } from 'pinia'
export const useStore = defineStore('storeId', {
state: () => {
return {
counter: 100,
}
},
getters: {},
actions: {}
})
  • 去Home.vue中打印下counter, 看能否拿到
<template>
<div>
<h1>Home</h1>
<h1>{{ store.counter }}</h1> <!-- 测试pinia能否拿值 -->
</div>
</template>

<script setup>
import { useStore } from '../store'
const store = useStore(); //


</script>

<style scoped></style>

STEP2: pinia的二次封装

  • 问题: 如果”桶”太多了, 没有目录很难找
  • 解决方法: index.ts不存值, 这个桶专门当做目录
image.png|500 image.png|307
import { defineStore } from 'pinia'
import { testStore } from './testStore'

// index.ts相当于目录, 方便后续管理多个store
export const useStore = defineStore('storeId', {
state: () => {
return {
user: testStore(), // 测试桶
// ...后续还有什么桶, 都放这里
}
},
getters: {},
actions: {}
})

测试桶

import { defineStore } from 'pinia'

export const testStore = defineStore('userId', {
state: () => {
return {
count: 100,
}
},
getters: {},
actions: {},
})

  • test是目录, 一定要useStore()才拿到目录
<script setup lang="ts">
import { useStore } from '../store'

const store = useStore().test;

</script>

<template>
<h1>TestPanel</h1>
<p>{{store.counter}}</p>
</template>

<style scoped>

</style>

STEP3: pinia插件实现 持久化存储

  • 一般的pinia: userStore.token = 'abc'网页刷新后就变回去了, 无法持久化数据, 但是使用persistedstatepinia插件, 就可以实现在浏览器的localStoreage中存储数据
    image.png
  • 下载pinia插件: 下载安装:npm install pinia-plugin-persistedstate (pinia-plugin-persist已经过时)
  • mian.ts中use下
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App);

// 1.使用路由
import router from './router';
app.use(router);

// 2.使用pinia状态管理
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(piniaPluginPersistedstate) // 注册数据持久化插件
app.use(store);


app.mount('#app');

import { defineStore } from 'pinia'

export const useUserStore = defineStore('userId', {
state: () => {
return {
name: 'Tlyer233',
token: "1234",
}
},
getters: {},
actions: {},


persist: { // pinia的插件--数据持久化存储
storage: localStorage,
// paths: ['name', 'token'] // 不写就是全部存储; 写的话就是只持久化指定字段
}
})
<template>
<div>
<h1>Home</h1>
<h1>{{ userStore.name }}</h1> <!-- 测试pinia能否拿值 -->
<button @click="userStore.token = 'abc'">Change Token</button>
<p>{{ userStore.token }}</p>
</div>
</template>

<script setup>
import { useStore } from '../store/index'

const userStore = useStore().user; // 测试pinia持久化存储


</script>

<style scoped></style>

第四节 路径别名(vite配置)

image.png|1025 image.png|275
  • 说明: 这两个文件都是根路径下的(下面如果没说是根, 默认是src/renderer/src起始)
import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin, bytecodePlugin } from 'electron-vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
main: {
plugins: [externalizeDepsPlugin(), bytecodePlugin()]
},
preload: {
plugins: [externalizeDepsPlugin(), bytecodePlugin()]
},
renderer: {
resolve: {
// vite配置1:路径别名
alias: {
'@renderer': resolve('src/renderer/src'),
'@store': resolve('src/renderer/src/store'),
'@views': resolve('src/renderer/src/views'),
'@router': resolve('src/renderer/src/router'),
'@components': resolve('src/renderer/src/components'),
}
},
plugins: [vue()]
}
})

这个不配置的话, ts不认识, ts没有提示, 会报错(虽然可能可以运行)

{
"extends": "@electron-toolkit/tsconfig/tsconfig.web.json",
"include": [
"src/renderer/src/env.d.ts",
"src/renderer/src/**/*",
"src/renderer/src/**/*.vue",
"src/preload/*.d.ts"
],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": { // 路径别名
"@renderer/*": [
"src/renderer/src/*"
],
"@store/*": [
"src/renderer/src/store/*"
],
"@views/*": [
"src/renderer/src/views/*"
],
"@router/*": [
"src/renderer/src/router/*"
],
"@components/*": [
"src/renderer/src/components/*"
]
}
}
}
  • 然后把之前, router那些路径改下….
import { defineStore } from 'pinia'
import { useUserStore } from '@store/useUserStore'

// index.ts相当于目录, 方便后续管理多个store
export const useStore = defineStore('storeId', {
state: () => {
return {
user: useUserStore(), //用户桶

}
},
getters: {},
actions: {}
})

第五节 Element Plus

//element
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
renderer: {
resolve: {
alias: {
'@renderer': resolve('src/renderer/src'),
}
},
server:{
"proxy":{
...
}
},
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
})
]
}
})
  • Title:
  • Author: 明廷盛
  • Created at : 2026-05-01 00:50:08
  • Updated at : 2026-05-01 00:50:08
  • Link: https://blog.20040424.xyz/2026/05/01/⚔️实战项目/4.Electron/
  • License: All Rights Reserved © 明廷盛