当前位置: 首页 > news >正文

使用vite+vue3+ElementPlus+pinia搭建中后台应用-前端

使用vite+vue3+ElementPlus+pina搭建中后台应用

  • 新建项目
  • 引入ElementPlus
    • 安装
    • 使用
    • 引入样式
      • 自定义主题
    • 布局
    • 引入Pinia
      • 安装
      • hooks-useWindow
        • 工具库-获取浏览器信息和窗口大小
      • store存储菜单状态
      • 处理菜单折叠
      • 在header处理折叠
        • 引入 @element-plus/icons-vue
    • 引入vue-router
    • 网络请求

进度 2025-10-30

在这里插入图片描述

仓库地址
https://github.com/codehskdog/system-manager

新建项目

使用vite新建一个vue3+ts项目
我的vite版本是7.17, vue为3.5.22
npm init vite@latest
在这里插入图片描述
使用你喜欢的包管理工具安装依赖。
安装完成后执行
npm run dev

引入ElementPlus

安装

选择你喜欢的包管理器安装即可 npm/yarn/pnpm
pnpm install element-plus

使用

这里使用按需引入。

需要安装pnpm install -D unplugin-vue-components unplugin-auto-import

修改vite.config.ts

import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],
});

App.vue中,根组件为

<script setup lang="ts"></script><template><el-config-provider><!-- ... --></el-config-provider>
</template>

引入样式

尝试下
在这里插入图片描述
在这里插入图片描述
没有引入样式就正常显示了。why?自动导入插件帮我们做了

自定义主题

新建文件 src/styles/index.scss
这里可以写自己项目的样式。
然后在main.ts引入
比如我们这样写。

body {width: 100vw;height: 100vh;margin: 0;
}#app {width: 100%;height: 100%;
}

新建文件 src/styles/element/var.scss 写一些自定义的主题
控制台可能会报错,说你却少sass依赖,根据它的提示安装就好。
在这里插入图片描述
在这里重写一些定义

@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ('primary': ('base': #003261,),'success': ('base': #21ba45,),'warning': ('base': #f2711c,),'danger': ('base': #db2828,),'error': ('base': #db2828,),'info': ('base': #42b8dd,),),$button-padding-horizontal: ('default': 80px,)
);

配置vite.config.ts
配置别名 '@': path.resolve(__dirname, 'src'),

import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import path from 'path';export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver({importStyle: 'sass',}),],}),],resolve: {alias: {'@': path.resolve(__dirname, 'src'),},},css: {preprocessorOptions: {scss: {additionalData: `@use "@/styles/element/var.scss" as *;`,},},},
});

主要是配置css预处理选项,然后因为是按需导入,需要配置自动导入的为scss。
在这里插入图片描述

布局

新建一个目录
src/layout
新建一个文件scr/layout/index.vue
layout目录下新建两个目录 src/layout/pc src/layout/mobile
分别新建index.vue
在这里插入图片描述

将App.vue中的
在这里插入图片描述
移动到src/layout/index.vue 并且在App.vue引入src/layout/index.vue
在这里插入图片描述

此刻可能会提示找不到定义什么的。
修改tsconfig.app.json 增加baseUrl和paths。
在这里插入图片描述

这里先不管 mobile/index.vue,先完善pc/index.vue

<template><el-container><el-aside width="200px"> <Menu /></el-aside><el-container><el-header><Header /></el-header><el-main><Page /></el-main></el-container></el-container>
</template><script setup>
import Menu from './Menu.vue';
import Header from './Header.vue';
import Page from './Page.vue';
</script><style></style>

layout/index.vue引入使用
在这里插入图片描述
在pc目录下新增几个组件,并在pc/index.vue引入使用
在这里插入图片描述
修改下 el-header的默认padding和高度
这里你可以看看element-plus的定义找到header的
在这里插入图片描述
在这里插入图片描述
对于aside的宽度,我们查看下元素,发现–el-aside-width未定义

在这里插入图片描述
我们可以自己定义
在这里插入图片描述
说白了,他这个定义也就是注入到root,我们同样可以。包括定义$header-bg-color的颜色。
header.vue

<template><div class="header"></div>
</template><script setup lang="ts"></script><style scoped lang="scss">
.header {width: 100%;height: 100%;background-color: $header-bg-color;
}
</style>

当然我这里使用的是scss,你也可以使用一些原子化的样式。

Menu.vue

<template><div class="menu"></div>
</template><script setup lang="ts"></script><style style lang="scss">
.menu {width: 100%;height: 100vh;background-color: $menu-bg-color;
}
</style>

在这里插入图片描述
然后Page.vue
此时我们的内容存放位置el-main
在这里插入图片描述
所以Page暂时比较简单,先把router-view写进来,虽然还没开始使用vue-router
page.vue

<template><div class="content"><router-view></router-view></div>
</template><script setup lang="ts"></script><style lang="scss" coped>
.content {width: 100%;height: 100%;
}
</style>

到此布局简单完成。

布局就像我们一个人,无论你穿什么样子的衣服,你总是有头,身体,四肢对吧,然后我们就可以戴帽子,穿衣服,做搭配?layout/index.vue可以理解为试衣间,给我们提供数据等等。

引入Pinia

https://pinia.vuejs.org/core-concepts/

安装

pnpm add pinia

新增目录
src/stores并在此目录下增加index.ts

负责处理Pinia的注册。

import { createPinia } from 'pinia';const pinia = createPinia();export default pinia;

在main.ts中引入

import { createApp } from 'vue';
import App from './App.vue';
import '@/styles/index.scss';
import pinia from '@/stores/index';const app = createApp(App);app.use(pinia).mount('#app');

hooks-useWindow

工具库-获取浏览器信息和窗口大小

修改tsconfig的配置
在这里插入图片描述

新增目录 src/utils 负责存放公共工具方法。并新增index.ts文件
在这里插入图片描述

新增enums.ts文件

// 屏幕尺寸枚举
export enum ScreenSize {XS = 'xs', // <768pxSM = 'sm', // 768px~991pxMD = 'md', // 992px~1199pxXL = 'xl', // 1200px~1919pxFULL = 'full', // >=1920px
}// 浏览器类型枚举
export enum BrowserType {CHROME = 'chrome',SAFARI = 'safari',FIREFOX = 'firefox',OPERA = 'opera',MSIE = 'msie',OTHER = 'other',
}// 设备标签枚举
export enum DeviceTag {PC = 'pc',MOBILE = 'mobile',PAD = 'pad',ANDROID_PAD = 'androidPad',
}// 浏览器前缀枚举
export enum BrowserPrefix {WEBKIT = 'webkit',MS = 'ms',MOZ = 'Moz',O = 'O',
}

utils/index.ts

import { ScreenSize, BrowserType, DeviceTag, BrowserPrefix } from './enums'; // 导入枚举export function getBrowser() {const docEl = document.documentElement;const ua = navigator.userAgent.toLowerCase();const { platform } = navigator;const { clientWidth: width, clientHeight: height } = docEl;// 1. 检测浏览器类型let browserType: BrowserType = BrowserType.OTHER;if (ua.includes('firefox')) {browserType = BrowserType.FIREFOX;} else if (ua.includes('chrome')) {browserType = BrowserType.CHROME;} else if (ua.includes('safari')) {browserType = BrowserType.SAFARI;} else if (ua.includes('opera') || ua.includes('opr')) {browserType = BrowserType.OPERA;} else if (ua.includes('msie') || ua.includes('trident')) {browserType = BrowserType.MSIE;}// 2. 检测设备类型const isTouchDevice ='ontouchstart' in window || ua.includes('touch') || ua.includes('mobile');let deviceTag: DeviceTag = DeviceTag.PC;if (isTouchDevice) {if (ua.includes('ipad')) {deviceTag = DeviceTag.PAD;} else if (ua.includes('mobile')) {deviceTag = DeviceTag.MOBILE;} else if (ua.includes('android')) {deviceTag = DeviceTag.ANDROID_PAD;}}// 3. 确定浏览器前缀(使用枚举映射)const prefixMap: Record<BrowserType, BrowserPrefix> = {[BrowserType.CHROME]: BrowserPrefix.WEBKIT,[BrowserType.SAFARI]: BrowserPrefix.WEBKIT,[BrowserType.FIREFOX]: BrowserPrefix.MOZ,[BrowserType.OPERA]: BrowserPrefix.O,[BrowserType.MSIE]: BrowserPrefix.MS,[BrowserType.OTHER]: BrowserPrefix.WEBKIT,};const browserPrefix = prefixMap[browserType];// 4. 检测操作系统平台const osPlatform = ua.includes('android')? 'android': platform.toLowerCase();// 5. 屏幕尺寸分级(使用 ScreenSize 枚举)let screenSize: ScreenSize = ScreenSize.FULL;if (width < 768) {screenSize = ScreenSize.XS;} else if (width < 992) {screenSize = ScreenSize.SM;} else if (width < 1200) {screenSize = ScreenSize.MD;} else if (width < 1920) {screenSize = ScreenSize.XL;}// 6. 衍生辅助判断const isIOS = /\(i[^;]+;( u;)? cpu.+mac os x/.test(ua);const isPC = deviceTag === DeviceTag.PC;const isMobile = !isPC;const isMini = screenSize === ScreenSize.XS || isMobile;return {width,height,type: browserType,prefix: browserPrefix,plat: osPlatform,tag: deviceTag,screen: screenSize,isMobile,isIOS,isPC,isMini,};
}

useWindow.ts

import { onMounted, onUnmounted, ref } from 'vue';
import { getBrowser } from '@/utils/index'; // 导入浏览器信息检测函数
import {ScreenSize,BrowserType,DeviceTag,BrowserPrefix,
} from '@/utils/enums'; // 导入类型export type BrowserInfo = {width: number;height: number;type: BrowserType;prefix: BrowserPrefix;plat: string;tag: DeviceTag;screen: ScreenSize;isMobile: boolean;isIOS: boolean;isPC: boolean;isMini: boolean;
};
export const useWindow = () => {// 用ref存储响应式浏览器信息const browserInfo = ref<BrowserInfo>({} as BrowserInfo);const needCollapse = ref(false);// 更新浏览器信息的方法const updateBrowserInfo = () => {browserInfo.value = getBrowser();const need = [ScreenSize.XS, ScreenSize.SM, ScreenSize.MD];if (need.includes(browserInfo.value.screen)) {needCollapse.value = true;} else {needCollapse.value = false;}};// 初始化信息updateBrowserInfo();// 监听窗口变化(无节流,实时触发)window.addEventListener('resize', updateBrowserInfo);onUnmounted(() => {// 移除监听,避免内存泄漏window.removeEventListener('resize', updateBrowserInfo);});return {browserInfo,needCollapse,// 手动更新方法updateBrowserInfo,};
};

store存储菜单状态

在这里插入图片描述

import { useWindow } from '@/hooks/useWindow';
import { defineStore } from 'pinia';
import { ref, watch } from 'vue';export const useGlobalStore = defineStore('global', () => {const { browserInfo, needCollapse } = useWindow();watch(() => browserInfo.value.screen,(v) => {menuCollapsed.value = needCollapse.value;});const menuCollapsed = ref(needCollapse.value);const collapsedMenu = () => {menuCollapsed.value = true;};const expandMenu = () => {menuCollapsed.value = false;};return { menuCollapsed, collapsedMenu, expandMenu, browserInfo };
});

处理菜单折叠

这个时候可以先把el-aside的宽度设置为auto
在这里插入图片描述

Menu.vue

<template><el-menu default-active="2"   :collapse-transition="false" :collapse="menuCollapsed" class="menu"><el-menu-item index="2"><template #title>Navigator Two</template></el-menu-item><el-menu-item index="3" disabled><template #title>Navigator Three</template></el-menu-item><el-menu-item index="4"><template #title>Navigator Four</template></el-menu-item></el-menu>
</template><script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useGlobalStore } from '@/stores/modules/global';
import { storeToRefs } from 'pinia';
const store = useGlobalStore();
const { menuCollapsed } = storeToRefs(store);
const width = computed(() => {return menuCollapsed.value ? '80px' : '200px';
});
</script><style style lang="scss" scoped>
.menu {width: 100%;height: 100vh;width: v-bind(width);
}
</style>

在header处理折叠

引入 @element-plus/icons-vue

pnpm install @element-plus/icons-vue

在这里插入图片描述
使用Expand和Fold
先去掉 背景色,加个border区分。

<template><div class="header"><el-icon size="20" class="icon"><component:is="menuCollapsed ? Expand : Fold"@click="changeMenuCollapsed"/></el-icon></div>
</template><script setup lang="ts">
import { useGlobalStore } from '@/stores/modules/global';
import { Expand, Fold } from '@element-plus/icons-vue';const { menuCollapsed, changeMenuCollapsed } = useGlobalStore();
</script><style scoped lang="scss">
.header {display: flex;align-items: center;box-sizing: border-box;padding: 0 10px;width: 100%;height: 100%;border-bottom: 1px solid #e3e3e3;// background-color: $header-bg-color;.icon {cursor: pointer;}
}
</style>

引入vue-router

安装pnpm add vue-router@4
新建目录src/router
新建目录src/views
在views目录下新建两个vue文件,随便输入点内容
在这里插入图片描述

<template><div>Home</div>
</template><script></script><style></style>

src/router下新增index.ts

import { createWebHashHistory, createRouter } from 'vue-router';const routes = [{ path: '/', component: () => import('@/views/Home.vue') },{ path: '/about', component: () => import('@/views/About.vue') },
];const router = createRouter({history: createWebHashHistory(),routes,
});export default router;

在main.ts中引入
在这里插入图片描述

有了router后再改下Menu

<template><el-menudefault-active="/":collapse="menuCollapsed":collapse-transition="false"class="menu"router><el-menu-item index="/"><el-icon><HomeFilled /></el-icon><template #title>首页</template></el-menu-item><el-menu-item index="/about"><el-icon><Setting /></el-icon><template #title>About</template></el-menu-item></el-menu>
</template><script setup lang="ts">
import { HomeFilled, Setting } from '@element-plus/icons-vue';
import { computed, ref, watch } from 'vue';
import { useGlobalStore } from '@/stores/modules/global';
import { storeToRefs } from 'pinia';
const store = useGlobalStore();
const { menuCollapsed } = storeToRefs(store);
const width = computed(() => {return menuCollapsed.value ? '80px' : '200px';
});
</script><style style lang="scss" scoped>
.menu {width: 100%;height: 100vh;width: v-bind(width);
}
</style>

到此就有了一个大概的框架。

在这里插入图片描述

网络请求

一般我们的页面渲染可以理解为Render(data)
我们负责写Render,而后端提供data。
网络请求接入。
一般使用axios,或者可以尝试下umi的一个中间件umi-request
umi-request文档地址
安装
pnpm install --save umi-request
在这里插入图片描述
我们也用创建实例的方式
在这里插入图片描述
新增文件src/api/index.ts
在这里插入图片描述
PS:2025-10-30暂停前端开发,先搭建后端

http://www.dtcms.com/a/549248.html

相关文章:

  • 开始改变第六天 MySQL(2)
  • 如何使用wordpress搭建网站广告咨询
  • 网站建设那个好北京大兴专业网站建设公司
  • 基于 GEE 的融合 MODIS 地表反射率、MCD12Q1 土地覆盖与 TERRACLIMATE 气候数据的研究区净初级生产力(NPP)计算方法研究
  • markdown-it
  • vector 的扩容机制
  • part1~2 神经网络基础
  • SQL注入过滤绕过fuzz字典
  • CH32 WCH-LINK -Error: Failed to Open WCH-Link.
  • 构建AI智能体:七十九、从SVD的理论到LoRA的实践:大模型低秩微调的内在逻辑
  • Blackwell GPU提供LLVM和MLIR支持的相关工作 报告
  • 宁波网站开发建设网上做娱乐广告的网站
  • 浙江制造品牌建设网站做微信网站公司名称
  • Babylon.js中ArcRotateCamera.interpolateTo 方法使用备忘
  • 【OD刷题笔记】- CPU算力分配
  • iOS 抓包工具有哪些,开发者的选型与实战指南
  • 测试过程涉及python自动化及其他相关面试问题汇总
  • 免费网站建设讯息全站加速 wordpress
  • 哪里网站建设公司比较好网站建设销售工作职责
  • 推荐一款免费的语音识别网站,上传音频即可
  • 笔记C++语言,太焦虑了
  • 分公司一般做网站吗音乐网站建设目标
  • Java 21 虚拟线程 vs 缓存线程池与固定线程池
  • 在线开发培训网站建设小型餐饮店面设计
  • ZYNQ USB按键读写操作详解:从裸机到Linux系统的完整实现
  • 如何在Windows桌面实现自由悬浮计时?
  • BEV环视感知算法从环境部署开始
  • 看上去高端的网站深圳培训学校
  • 狂飙与重构:机器人IPO浪潮背后的系统焦虑与感知进化
  • 21.静态NAT