Vue3 + Element Plus 做后台管理系统,这些关键问题得搞懂!
为啥选 Vue3 搭配 Element Plus 做后台管理系统?
做后台系统时,技术选型得兼顾开发效率、组件成熟度和性能,Vue3 和 Element Plus 的组合,刚好在这些维度形成互补:
Vue3 解决“底层基建”问题
- 开发体验更灵活:组合式 API(Composition API)让逻辑复用更丝滑,比如把表格的分页、请求逻辑抽成自定义 Hook,多个页面能直接复用;
refreactive替代传统data,响应式写法更简洁直观。 - 性能优势显著:编译阶段的静态标记优化、响应式底层重构(用 Proxy 替代 Object.defineProperty),让页面渲染和更新速度大幅提升,后台系统里表格、弹窗多,性能好能直接减少操作卡顿感。
- 生态适配完善:Vue Router 4、Pinia 等核心工具都对 Vue3 深度支持,社区插件丰富,遇到问题能快速找到解决方案。
Element Plus 搞定“上层组件”落地
- 高频组件即用性强:表格(ElTable)、表单(ElForm)、弹窗(ElDialog)等后台核心组件,样式和逻辑都封装得很成熟,ElTable 自带分页、多选、排序功能,改改配置就能直接用,不用重复造轮子。
- 对 Vue3 特性深度适配:基于 Vue3 的 Teleport、Suspense 等新特性重构组件,像弹窗组件用 Teleport 把内容挂载到 body 上,避免样式嵌套冲突;组件内部用组合式 API 编写,和业务代码风格更统一。
- 社区与文档友好度高:官方文档提供丰富代码示例,遇到问题“抄作业”就能解决;GitHub 社区活跃,Bug 修复和功能迭代速度快,还有第三方封装的表格树形结构、Excel 导出等工具可直接复用。
从零开始初始化项目,步骤得注意啥?
很多新手一上来就盲目装依赖,其实初始化时选工具、配组件、规划结构都有门道:
选对脚手架,启动效率翻倍
当下更推荐用 Vite 替代 Vue CLI,Vite 基于 ESModule 实现,冷启动秒级响应,热更新也更快,创建项目命令:
npm create vite@latest my-admin -- --template vue
进入项目后执行 npm install 装依赖,再用 npm run dev 就能快速启动开发服务,若团队习惯 Webpack 生态,也可选择 Vue CLI,但从长远技术趋势看,Vite 更值得优先学习。
Element Plus 安装,“按需导入”更省体积
全量导入 Element Plus 会把所有组件打包,导致项目体积臃肿。自动按需导入是更聪明的选择:先安装两个核心插件:
npm install unplugin-vue-components unplugin-auto-import -D
接着在 vite.config.js 中配置插件,实现组件和工具函数的自动导入:
import { defineConfig } from '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({
plugins: [
Vue(),
AutoImport({
resolvers: [ElementPlusResolver()], // 自动导入 ElMessage 等工具函数
}),
Components({
resolvers: [ElementPlusResolver()], // 自动导入 ElButton 等组件
}),
],
})
这样写代码时直接用 <el-button>,插件会自动引入对应组件和样式,打包体积能减少一半以上。
项目结构提前规划,后期少踩坑
后台系统的目录结构建议按功能模块化划分,核心目录作用如下:
src/api:存放接口请求函数,用 axios 封装请求/响应拦截器(如统一加 Token、处理错误码)。src/components:封装通用组件(如布局 Header、Sidebar、全局弹窗)。src/router:配置路由,区分公开路由(如登录页)和受保护路由(如 Dashboard)。src/store:用 Pinia 做状态管理,存储用户信息、权限等全局状态。src/views:存放页面级组件,每个页面对应一个路由。
以路由配置为例,src/router/index.js 可这样设计:
import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/views/Login.vue'
import Layout from '@/components/Layout.vue'
// 公开路由(无需登录即可访问)
const publicRoutes = [
{ path: '/login', component: Login },
{ path: '/', redirect: '/login' }
]
// 受保护路由(需登录 + 权限验证)
const privateRoutes = [
{
path: '/dashboard',
component: Layout,
children: [
{ path: '', component: () => import('@/views/Dashboard.vue') }
]
}
]
const router = createRouter({
history: createWebHistory(),
routes: [...publicRoutes, ...privateRoutes]
})
export default router
后期添加权限控制时,privateRoutes 可改为动态加载,根据用户角色生成可访问路由表。
后台系统核心的权限管理,咋落地?
权限分为路由权限(用户能访问哪些页面)和按钮权限(页面内哪些按钮可操作),需结合前端路由和状态管理实现:
路由权限:动态加载,按需渲染
核心思路是“登录后,后端返回用户可访问路由列表,前端动态添加路由”,步骤如下:
-
登录时,接口返回
roles(如['admin', 'editor'])和accessibleRoutes(路由配置数组)。 -
用 Pinia 存储用户角色和权限,示例代码:
// src/store/user.js import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ roles: [], permissions: [] // 按钮权限标识,如 ['add', 'delete'] }), actions: { setRoles(roles) { this.roles = roles }, setPermissions(permissions) { this.permissions = permissions } } }) -
前端根据
accessibleRoutes,调用router.addRoute()动态添加路由,登录逻辑示例:// src/views/Login.vue import { useUserStore } from '@/store/user' import router from '@/router' const login = async () => { const res = await api.login(loginForm) const { roles, accessibleRoutes, permissions } = res.data const userStore = useUserStore() userStore.setRoles(roles) userStore.setPermissions(permissions) // 动态添加路由 accessibleRoutes.forEach(route => router.addRoute(route)) router.push('/dashboard') }
按钮权限:自定义指令,精准控制
针对“部分按钮仅特定角色可见”的需求,可通过自定义指令实现,步骤如下:
- 编写指令逻辑:检查用户权限数组是否包含目标标识,不包含则删除按钮 DOM。
- 全局注册指令,页面中用
v-permission="'标识'"控制按钮显示。
指令代码示例:
// src/directive/permission.js
export const permissionDirective = {
mounted(el, binding) {
const { value } = binding
const userStore = useUserStore() // 从 Pinia 取权限
if (value && !userStore.permissions.includes(value)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
// src/main.js 全局注册
import { createApp } from 'vue'
import App from './App.vue'
import { permissionDirective } from './directive/permission'
const app = createApp(App)
app.directive('permission', permissionDirective)
app.mount('#app')
页面中使用指令:
<el-button type="danger" v-permission="'delete'">删除</el-button>
表格和表单高频场景,咋高效开发?
后台系统中,表格(数据查询)和表单(数据增删改)占比超 80%,结合 Element Plus 需学会“封装 + 复用”:
表格:抽离逻辑,减少重复代码
Element Plus 的 ElTable 组件,每次写分页、请求、排序都很繁琐,用组合式 API 封装自定义 Hook,可大幅减少重复代码,示例 useTable Hook:
// src/hooks/useTable.js
import { ref, onMounted } from 'vue'
export function useTable(apiFn) { // apiFn 为获取表格数据的接口函数
const tableData = ref([])
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const fetchData = async () => {
const res = await apiFn({ page: page.value, pageSize: pageSize.value })
tableData.value = res.list
total.value = res.total
}
onMounted(() => fetchData())
return { tableData, page, pageSize, total, fetchData }
}
页面中使用 Hook:
<template>
<el-table :data="tableData">
<el-table-column prop="name" label="名称" />
<el-table-column prop="age" label="年龄" />
</el-table>
<el-pagination
v-model:page="page"
v-model:page-size="pageSize"
:total="total"
@size-change="fetchData"
@page-change="fetchData"
/>
</template>
<script setup>
import { useTable } from '@/hooks/useTable'
import { getTableList } from '@/api/table' // 接口函数
const { tableData, page, pageSize, total, fetchData } = useTable(getTableList)
</script>
分页、请求等逻辑被 Hook 封装后,新页面只需传入接口函数即可复用。
表单:配置化 + 验证,提效 50%
Element Plus 的 ElForm 支持表单验证,但重复编写 rules 过于繁琐,可通过配置化表单简化开发:用 JSON 定义表单项,循环渲染表单,示例:
<template>
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item
v-for="(item, index) in formConfig"
:key="index"
:label="item.label"
:prop="item.prop"
>
<el-input v-if="item.type === 'input'" v-model="form[item.prop]" />
<el-select v-if="item.type === 'select'" v-model="form[item.prop]">
<el-option
v-for="opt in item.options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
</el-form-item>
<el-button type="primary" @click="submit">提交</el-button>
</el-form>
</template>
<script setup>
import { ref } from 'vue'
const formRef = ref()
const form = ref({ username: '', gender: '' })
const rules = {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }]
}
const formConfig = [
{ label: '用户名', prop: 'username', type: 'input' },
{
label: '性别',
prop: 'gender',
type: 'select',
options: [
{ label: '男', value: 'male' },
{ label: '女', value: 'female' }
]
}
]
const submit = () => {
formRef.value.validate((valid) => {
if (valid) { /* 调用接口提交数据 */ }
})
}
</script>
后续新增表单项时,只需在 formConfig 中添加配置对象,无需修改模板,特别适合需求频繁变更的场景。
项目做大后,性能优化从哪些方面入手?
后台系统数据多、组件杂,性能不佳会严重影响用户体验,结合 Vue3 和 Element Plus,可从以下方向优化:
组件层面:按需加载 + 虚拟滚动
- 路由懒加载:用
() => import('@/views/Dashboard.vue')替代直接导入,确保首屏仅加载必要组件。 - Element Plus 组件按需导入:前文提到的自动导入插件已实现此功能,避免全量打包冗余代码。
- 虚拟列表:处理万条数据的表格时,使用
vue-virtual-scroller或自定义虚拟滚动组件,仅渲染可视区域 DOM,ElTable 渲染 1000 行数据时,虚拟滚动可将 DOM 节点从千级压缩到几十级,大幅提升性能。
状态管理:Pinia 轻量更高效
Pinia 对 Vue3 优化更友好,无需手动编写 mutations,代码更简洁;其响应式机制自动触发更新,减少不必要的性能消耗,拆分 Store 时,建议按模块(如用户、权限、表格数据)划分,避免单个 Store 过于臃肿。
HTTP 请求:拦截 + 缓存
用 axios 封装请求拦截器(统一添加 Token、处理请求头)和响应拦截器(统一处理错误码、Token 过期跳转登录);对 GET 请求添加缓存策略(如用 localStorage 存储请求结果,相同参数直接读取缓存),减少接口请求次数。
编译优化:Vite + Tree Shaking
Vite 原生支持 Tree Shaking(摇树优化),可剔除未使用代码,打包时开启 build.minify: 'terser',压缩代码更彻底;给组件添加 defineOptions({ name: 'MyComponent' }),帮助 Tree Shaking 精准识别冗余代码。
想拓展功能,能和哪些生态工具联动?
Vue3 + Element Plus 并非孤立存在,与以下工具联动可拓展系统能力:
图表:ECharts + Vue 组件封装
后台数据可视化首选 ECharts,封装 Vue 组件统一管理 ECharts 初始化、更新逻辑,结合 Element Plus 布局组件(ElRow、ElCol)展示图表:
<template>
<div ref="chartRef" style="width: 600px; height: 400px" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
const chartRef = ref()
onMounted(() => {
const chart = echarts.init(chartRef.value)
chart.setOption({
xAxis: { type: 'category', data: ['周一', '周二'] },
yAxis: { type: 'value' },
series: [{ data: [120, 200], type: 'bar' }]
})
})
</script>
富文本:TinyMCE / Quill + Vue3 封装
后台发布文章、编辑公告需富文本编辑器,TinyMCE 功能全面(支持图片上传、表格、代码块),Quill 轻量易定制,使用 Vue3 封装版组件(如 @tinymce/tinymce-vue),在 Element Plus 弹窗中使用:
<el-dialog title="编辑内容" v-model="dialogVisible">
<TinyMCE v-model="content" :options="tinyOptions" />
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</template>
</el-dialog>
低代码表单:Formily + Element Plus
若表单逻辑复杂(如字段联动、动态表单项),Formily 可大幅减少开发量,它与 Element Plus 深度整合,通过 Schema 定义表单,支持可视化配置,例如前文的配置化表单,Formily 可自动处理验证、联动,甚至生成代码,效率翻倍。
Vue3 + Element Plus 做后台管理系统,核心是技术选型匹配场景(Vue3 负责性能与开发体验,Element Plus 负责组件快速落地)、流程化开发(初始化、权限、高频场景封装)、性能与生态拓展(优化用户体验,联动工具提效)。
实际开发中,需结合业务灵活调整(如权限复杂时引入 RBAC 模型,表单需求多变时采用低代码工具),但只要吃透上述关键问题,从 0 到 1 搭建后台系统基本不会踩大坑~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网

