前言
做过不少同类型的中后台和移动端项目,积累了一些经验和踩过的坑。这篇把共性的东西整理出来,重点讲做得好的、做得不好的、以及值得学的东西。
一、这些项目到底做了什么
总结下来就是三类形态:
Web 中后台——园区管理、企业服务、GIS 一张图。几乎所有页面都是”表格 + 表单 + 图表 + 地图”的组合,业务逻辑围绕审批流、监测数据、视频监控、应急指挥展开。
移动端 APP——与 Web 后台配套的移动端,核心是”看数据、收报警、做审批、巡检打卡”。用 uni-app 一套代码出 H5、安卓、iOS。
做完一堆项目后回头想,它们的本质高度一致:同一套技术能力 + 同一套业务模式 + 不同的地区/客户配置。
二、哪些地方做得好
1. 动态路由权限体系
不是简单的 v-if 控制菜单显隐,而是后端返回完整菜单树 → 前端动态生成路由表 → 注册到 router。核心在 router.beforeEach 里做异步路由注册,配合 Pinia 持久化 token 和菜单数据,刷新不丢。每新增一个客户或角色,前端零改动,后端配菜单即可。
2. GIS 可视化从二维到三维的渐进演进
早期用 OpenLayers 做二维标绘(画园区边界、标注点位),后来接入 Cesium 做三维展示(倾斜摄影、地下管网、模型压平)。两者并存的关键是各自操作独立 DOM 容器、独立数据格式,互不冲突。统一了坐标系转换层,OpenLayers 的投影坐标和 Cesium 的地理坐标之间自动换算。
3. 重依赖分包策略
中后台项目往往同时依赖 Cesium、three、echarts-gl、bpmn-js、xgplayer、tinymce 等重量级库。在 vite 的 build.rollupOptions.manualChunks 里手动分包,每种重依赖拆成独立 chunk;低频功能(exceljs、html2canvas)做动态 import(),只在用到时加载。不做优化时打包 30MB+,分包后主包控制在 2MB 以内。
4. 大屏实时数据方案
B/S 端基于 ECharts 做实时监控大屏,分辨率自适应用 transform: scale 等比缩放 + rem 做基础布局,适配各种屏幕比例。大数据量场景(几千个监测点实时数据)用 WebSocket + 增量更新替代全量轮询。
5. 跨端原生扩展的隔离设计
移动端需要设备上报、后台保活、推送等原生能力。通过 #ifdef APP-PLUS 条件编译集中放在 App.vue 的 onLaunch 中,原生调用和跨端逻辑完全隔离,不污染公共代码。
三、哪些需要改进
1. 技术栈版本碎片化
Vue2 和 Vue3 项目并行存在,部分 Web 后台还在用 Vue2 + Vuex + Webpack。新项目绝不开 Vue2 了,但老项目的迁移需要排期和业务窗口——不能为了升级技术栈而中断线上服务。
2. 重复造轮子严重
人员选择器、部门树、文件上传、地图拾取器……几乎每个项目都写了一遍。当时觉得”独立改起来方便”,但改一个 bug 要同步五六份代码。后续应抽进私有 npm 包统一维护,难点在于组件要足够通用又不能过度抽象——地图拾取器支持”单选/多选/回显/只读”四种模式,props 设计改了三版才定下来。
3. 文档几乎为零
除了 README 里一句 npm install && npm run dev,没有架构说明、目录介绍、环境配置文档。每次拉新项目都靠口口相传。应从 README 强制包含:技术栈、目录说明、本地跑起来的完整步骤、与后端联调的 baseURL 和代理配置。这件事不难,就是一直没做。
4. 依赖不清理
用 depcheck 扫了一圈,发现不少项目里装了但从未引用的包:swiper(所有页面都是列表型)、cropperjs(裁剪功能改后端处理了)、fabric(画布功能已砍),每次 npm install 都白白下载。应该养成习惯:每完成一个大版本用 depcheck 扫一遍,该删的删。
5. 移动端状态管理缺失
早期做的几个 APP 没加 Pinia,全局状态靠 uni.setStorageSync 和组件传参撑着。业务模块一多(报警、巡查、监测点、特殊作业等十几种),数据流就失控了——同一个用户信息可能在三个页面用不同方式存取。应统一接入 Pinia + persistedstate,和 Web 端保持一致。
6. 表格列数爆炸
中后台表格数据量不大(后端分页),但列数和操作多。几十列 + 每行五个操作按钮 + 有些列渲染组件(下拉、开关),DOM 数量直接爆炸。后续加了列配置功能让用户自定义显示列,固定列用 CSS position: sticky 替代组件库的 fixed 模式(后者会渲染多份 DOM)。
四、学到了什么——值得提炼的知识点
前端工程化完整链路
从一个项目里跑通了完整的前端工程化:TypeScript + ESLint + Prettier + Stylelint + Husky + lint-staged。这些工具单独用不稀奇,但串起来、跑起来、团队都遵守,需要一套清晰的配置和规则。
打包优化三板斧
manualChunks手动分包(vue / antdv / cesium / echarts 各自独立 chunk)resolve.alias统一依赖版本(lodash 和 lodash-es 别共存)- 动态
import()延迟加载低频模块
动态路由 + 权限的完整实现
不是网上教程里”写死几个角色”那种 demo,而是真正落地了:菜单接口 → 路由生成 → 导航守卫 → 按钮权限指令(v-permission)→ 刷新持久化。整个过程涉及 router API、Pinia store、后端接口协议三端的配合。
GIS 坐标系的理解
二维引擎(OpenLayers)和三维引擎(Cesium)的坐标系不同,前者常用 EPSG:3857(投影坐标),后者用弧度/经纬度。做统一转换层时理解了空间参考系统(SRS)和 Proj4 的基本概念,这对后续任何地图相关项目都有用。
组件抽象的度
不是抽得越多越好。一个组件如果为了”通用”加了 20 个 props 和 5 层 if-else,那还不如两个独立组件。抽象原则:对外只暴露必要 props 和 slots,内部封装复杂逻辑;如果某个场景花两行就能改好,就别往通用组件里塞。
uni-app 跨端的真实面貌
跨端不是”写完一次处处能跑”,而是”写完一次,在三个端各调一遍”。H5 端和 APP 端在路由动画、原生导航栏高度、底部安全区、条件编译粒度上都有差异,每个都要测到。真机调试比模拟器靠谱。
项目基线化管理
从”每个项目复制一份改一改”进化到”三层基线”:
| 层 | 职责 | 怎么管 |
|---|---|---|
| 技术基线 | 技术栈、构建、规范 | 脚手架固定,不允许随意改 |
| 组件基线 | ProTable、ProForm、选择器 | 私有 npm 包统一版本 |
| 配置层 | 地区、地址、功能开关 | 环境变量注入 |
五、实际可以聊的话题
把前面的内容梳理一下,日常面试和述职里,下面这些话题都有东西能说。
话题 1:项目体量和技术栈
我做的主要是中后台管理系统和配套的移动端。中后台用 Vue3 + Vite + Pinia + TypeScript + Ant Design Vue,移动端用 uni-app 做跨端。项目做了不少个,但仔细看它们的底层架构是一样的——动态路由权限、GIS 可视化、大屏监控、审批流——只是不同地区和客户的配置不一样。所以后来我把它们抽成了基线,新项目从基线起,改配置就行,不用从头搭。
要点:说明你做的不是”写页面”,而是理解了一个领域的通用架构。
话题 2:最复杂的一个技术点
权限体系。不是简单的登录验证,是完整的路由 + 按钮 + 数据三层控制。后端返回菜单树,前端
router.beforeEach里动态注册路由,按钮用自定义指令v-permission控制显隐。难点在于刷新后路由不能丢——Pinia 持久化存储 token 和菜单,beforeEach里做懒加载兜底。好处是每新增一个角色,后端配菜单就行,前端不用动一行代码。
要点:讲清”问题的本质是什么”和”你的解决思路”,不要说太细的代码细节。
话题 3:性能优化做过哪些
一个是打包体积优化。项目里同时用了 Cesium、three、echarts、bpmn-js 这些重依赖,不做优化的话打包出来 30 多 MB。我在 vite 的
manualChunks里把 vue、组件库、Cesium、echarts 各自拆成独立 chunk,低频库做动态 import,最后主包控制在 2MB 以内。另一个是大屏的实时数据。几千个监测点每秒都在推送数据,全量轮询服务端扛不住。改成 WebSocket + 增量更新,前端只更新变化了的数据点,图表用 ECharts 的
setOption局部更新而不是整体重绘。
要点:讲数据对比(30MB → 2MB),面试官喜欢有数字的说法。
话题 4:做过哪些技术决策
二维地图和三维场景要不要合并成一个引擎?最开始也想过都用 Cesium——毕竟三维也能看二维。但实际试下来,Cesium 做二维标绘体验很差,加载慢、交互重。OpenLayers 做二维轻、快、API 简洁。所以最后是双引擎并存,封装统一的坐标系转换层处理投影坐标和地理坐标的互转。代价是多维护一个依赖,收益是各自场景都用最合适的工具。
要点:讲 trade-off,说明你不是”查到什么用什么”,而是做过对比和决策。
话题 5:遇到过什么坑
一个是对”组件复用”的理解。早期为了复用,把一个选择器组件抽象得特别通用,props 加了十几个,里面各种 if-else 判断模式。结果用起来到处传参,改一个地方就影响其他地方。后来学到:组件抽象不要贪多,如果两个场景差异大,就写成两个组件,代码重复一点比过度抽象好维护。对外只暴露必要的 props 和 slots,复杂度关在组件内部。
要点:踩坑不可怕,能说清”学到了什么”就行。
话题 6:如果让你重新设计
首先统一技术栈,所有新项目全部上 Vue3,老项目排期逐步迁移。然后抽公共组件包,人员选择器、部门树、地图拾取器这些跨项目重复出现的,进私有 npm 包统一管理。移动端补齐 Pinia,现在有些 APP 还用 storage 硬传状态,业务一多就乱。最后每个仓库强制写好 README——技术栈、目录说明、怎么跑起来、后端联调地址,新人不用靠口口相传。
要点:体现你有复盘和改进意识。
聊项目时的原则
其实讲项目不用提前背稿,项目是你自己做的,本来就能说清。注意几点:
- 先讲”做什么”,再讲”怎么做”。面试官先关心你做的什么业务,再说技术细节。
- 对比要有数字。”优化后变快了”不如”构建时间从 40 秒降到 8 秒”。
- 踩坑是加分项。能讲出”我当时怎么想错了、后来怎么纠正的”,比讲”我搞了三套技术栈”印象深刻。
- 别报菜名。技术栈一句话带过就行,重点讲”用它解决了什么问题”。
- 诚实说不会的。遇到没做过的,就说”这块没深入过,我的理解是……”,比硬编强一万倍。
六、总结
几个习惯值得长期坚持:
- 新项目从基线起,不从头搭脚手架
- 做完一个版本清一次没用上的依赖
- 重复三次的代码必须抽成公共组件
- README 写清楚”新人怎么跑起来”
- 技术选型能少则少,多一套技术栈 = 多一倍的维护成本
项目整合趁早做。等技术债务大到搬不动的时候,再想改就只能重写了。
内容由 AI 生成,仅供参考。本文发布于 码上学习,转载请注明出处。