在现代 Web 应用开发中,后台管理系统扮演着至关重要的角色。然而,传统的构建方式往往面临着配置繁琐、启动缓慢等问题。为了解决这些痛点,并充分利用最新的前端技术,本文将深入探讨如何使用 Vite 和 Vue 3 这一强大的组合来构建高效、易维护的后台管理系统。Vite 凭借其极速的冷启动和热更新,极大地提升了开发效率,而 Vue 3 的 Composition API 和增强的性能,则为构建复杂应用提供了坚实的基础。我们将从项目初始化开始,逐步讲解核心功能的实现,包括路由管理(使用 Vue Router)、状态管理(使用 Pinia)、UI 组件库(例如 Element Plus)的应用、以及常见的权限控制和数据表格的处理等。通过本文的学习,你将掌握使用 Vite 和 Vue 3 构建后台管理系统的基本方法和最佳实践,并能够将其应用于实际项目中,构建出高效、现代化的后台管理系统。
1.项目展示
1.登录页
2.用户管理页
2.技术栈
"vite": "^6.0.5"
"axios": "^1.7.9"
"element-plus": "^2.9.2"
"pinia": "^2.3.0"
"vue": "^3.5.13"
"vue-router": "^4.5.0
"less": "^4.2.1"
2.项目搭建
本次项目我们使用 vite 进行构建。
官方文档地址:cn.vitejs.dev/
前提:安装 node 环境
使用 vite 创建 vue3 脚手架项目:
1.用脚手架创建项目
npm create vite@latest
2.安装依赖
npm install
项目中没有less、axios。elementUI-plus 需要单独安装
npm install axios
npm install less
npm install element-plus --save
axios文档:www.axios-http.cn/docs/intro
less文档:lesscss.cn/ 或者 less.js.cn/usage/
element-plus文档: element-plus.org/zh-CN/
4.启动项
这里可以先看一下项目是否可以启动成功。
npm run dev
5.修改 App.vue,删除默认的 HelloWorld 组件
4.配置 Element Plus
由于刚才已经安装过elementUI组件库了,所以现在只需要配置入口文件就可以了。
5.配置路由
import { createRouter, createWebHashHistory } from 'vue-router'
const routes = [
{
path: '/',
redirect: '/login',
},
{
path: '/login',
name: 'login',
meta: {
title: '登录',
},
component: () => import('../view/Login.vue'),
},
{
path: '/home',
name: '主页',
meta: {
title: '主页',
},
component: () => import('../view/Home.vue'),
redirect: '/index',
children: [
{
path: '/index',
meta: {
title: '首页',
},
component: () => import('../view/Welcome.vue'),
},
{
path: '/user/list',
meta: {
title: '用户管理',
},
component: () => import('../view/user/Index.vue'),
},
],
},
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
// 挂载路由导航守卫:to表示将要访问的路径,from表示从哪里来,next是下一个要做的操作
router.beforeEach((to, from, next) => {
// 修改页面 title
if (to.meta.title) {
document.title = '后台管理系统 - ' + to.meta.title
}
// 放行登录页面
if (to.path === '/login') {
return next()
}
// 获取token
const token = sessionStorage.getItem('token')
if (!token) return next('/login')
return next()
})
// 导出路由
export default router
6.配置axios
首先配置axios的请求拦截与响应拦截
import axios from 'axios'
import { ElMessage } from 'element-plus'
// 1. 创建axios实例
const instance = axios.create({
// 接口
baseURL: '/api',
// 超时时间
timeout: 50000,
})
// 2.请求拦截
instance.interceptors.request.use(
(config) => {
let token = sessionStorage.getItem('token')
if (token) {
config.headers['token'] = token
}
return config
},
(error) => {
// 请求发生错误,抛出异常
Promise.reject(error)
},
)
// 3.响应拦截
instance.interceptors.response.use(
(res) => {
return res
},
(error) => {
if (error && error.response) {
const status = error.response.status
switch (status) {
case 400:
ElMessage.error('请求错误')
break
case 401:
ElMessage.error('未授权,请重新登录')
break
case 403:
ElMessage.error('拒绝访问')
break
case 404:
ElMessage.error('请求错误,未找到相应的资源')
break
case 408:
ElMessage.error('请求超时')
break
case 500:
ElMessage.error('服务器内部错误')
break
case 501:
ElMessage.error('网络未实现')
break
case 502:
ElMessage.error('网络错误')
break
case 503:
ElMessage.error('服务不可用')
break
case 504:
ElMessage.error('网络超时')
break
case 505:
ElMessage.error('HTTP版本不支持该请求')
break
default:
ElMessage.error('请求失败')
}
} else {
if (JSON.stringify(error).includes('timeout')) {
ElMessage.error('服务器响应超时,请刷新页面')
}
ElMessage.error('连接服务器失败')
}
return Promise.reject(error)
},
)
// 4.导出 axios 实例
export default instance
封装请求组件
import instance from './axios'
const post = (url, data) => {
return new Promise((resolve, reject) => {
instance
.post(url, data)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
const get = (url, data) => {
return new Promise((resolve, reject) => {
instance
.get(url, { params: data })
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
const put = (url, data) => {
return new Promise((resolve, reject) => {
instance
.put(url, data)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
const del = (url, data) => {
return new Promise((resolve, reject) => {
instance
.delete(url, { data })
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
export default {
post,
get,
put,
del,
}
封装接口文件
import http from '../utils/http/http.js'
const login = (data) => {
return http.post("/user/login", data);
};
const getUserList = (data) => {
return http.get("/user/list", data);
};
const saveUser = (data) => {
return http.post("/user/save", data);
};
const delUser = (data) => {
return http.del("/user/delete", data);
};
const getUserDetail = (data) => {
return http.get("/user/detail", data);
};
export default {
login, getUserList, saveUser, delUser, getUserDetail
}
7.接口服务
手搓接口服务方便开发测试。 使用方法还是老样子。
npm install
// 需要注意的是此服务我是放在webscoketData文件夹内的,所以需要在webscoketData内运行npm install
//然后就是启动服务
node app.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// 使用 bodyParser 解析 JSON 数据
app.use(bodyParser.json());
// 模拟的数据库
let users = [
{ id: 1, username: 'john', email: 'john@example.com' },
{ id: 2, username: 'jane', email: 'jane@example.com' },
];
// 登录接口
const login = (data) => {
// 简单的登录模拟,检查用户名和密码
if (data.username === 'admin' && data.password === '1234') {
return { success: true, message: 'Login successful!' };
}
return { success: false, message: 'Invalid username or password' };
};
// 获取用户列表接口
const getUserList = () => {
return users;
};
// 获取单个用户详情接口
const getUserDetail = (id) => {
return users.find((user) => user.id === id);
};
// 保存用户接口
const saveUser = (data) => {
const newUser = { id: users.length + 1, ...data };
users.push(newUser);
return newUser;
};
// 删除用户接口
const delUser = (id) => {
users = users.filter((user) => user.id !== id);
return { success: true, message: 'User deleted successfully!' };
};
// POST 请求:登录接口
app.post('/user/login', (req, res) => {
const response = login(req.body);
res.json(response);
});
// GET 请求:获取用户列表
app.get('/user/list', (req, res) => {
const response = getUserList();
res.json(response);
});
// POST 请求:保存用户
app.post('/user/save', (req, res) => {
const response = saveUser(req.body);
res.json(response);
});
// DELETE 请求:删除用户
app.delete('/user/delete', (req, res) => {
const { id } = req.body;
const response = delUser(id);
res.json(response);
});
// GET 请求:获取用户详情
app.get('/user/detail', (req, res) => {
const { id } = req.query;
const response = getUserDetail(Number(id));
if (response) {
res.json(response);
} else {
res.status(404).json({ message: 'User not found' });
}
});
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
8.配置vite的代理及less打包插件(配置完成后重启项目)
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), vueDevTools()],
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true, //使用表达式的话必须开启
},
},
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
proxy: {
'/api': {
// 匹配以 /api 开头的请求路径
target: 'http://localhost:3000', // 目标服务器地址
changeOrigin: true, // 必须设置,用于欺骗浏览器,修改 Origin
rewrite: (path) => path.replace(/^\/api/, ''), // 可选,重写路径
},
},
},
})
9.登录页的
从这里还是细讲一下用到的知识点,这个页面主要用到的是Layout 布局,form表单,路由的跳转等。
10.后台主页
主页父组件
aside区代码
header区代码
Main区代码
11.本地打包及部署
本地化部署跳不过nginx的配置及启动,先手搓一个快速启动脚本
nginx的配置文件及打包文件
打包命令
npm run build
打包后的文件位置
12.总结
通过完成这个项目,你将对 Vue 3 的 Composition API、路由、API 交互等关键概念有更深入的理解,并提升你的前端开发能力。同时,你也可以将这个项目作为你作品集的一部分,展示你的技术水平。
项目地址 https://gitee.com/yilag/vite-vue3-project.git