|
去年帮一个做跨境电商的目开朋友重构后台系统,技术选型时他问我:“Vue 项目到底怎么搭才不会半年后变成屎山?发实”这个问题我听过太多次了。答案不在 Vue 本身,战案在于你动手前有没有想清楚三件事:状态往哪放、目开请求怎么管、发实组件怎么切。战案 我拿他那个后台举例。目开项目有 30 多个页面,发实权限分 5 种角色,战案数据看板要实时刷新。目开一开始他找了个模板,发实vue-element-admin 改的战案,跑起来挺快。目开三个月后加需求,发实改一个筛选条件,战案三个页面跟着崩。原因很简单——所有状态都塞在 Vuex 里,组件之间靠 commit 互相猜。后来我们重做,把状态拆成三层:全局的(用户信息、权限)放 Pinia,页面级的用 provide/inject,组件内部的就 ref。改完之后,一个页面出问题,最多查两层,不会牵一发动全身。 请求层是另一个重灾区。很多项目里 axios 封装就是加个 token、统一报错,然后散落在各个组件里调用。我见过一个页面里写了 12 个 api 调用,全在 mounted 里,一个失败全挂。我们的做法是建一个 services 目录,按业务模块分文件,每个文件导出函数。比如 order.js 里只放订单相关的请求,函数名就是 fetchOrderList、updateOrderStatus。组件里 import { fetchOrderList } from '@/services/order',一看就知道数据从哪来。拦截器只做两件事:401 跳登录,500 弹全局提示。业务错误在组件里处理,因为不同页面想展示的方式不一样。 组件切分有个土办法:如果一个组件超过 300 行,或者 template 里出现超过 3 层嵌套的 v-if,就该拆了。但拆也有讲究。我见过把按钮都拆成独立组件的,结果 props 传了 8 个,改个颜色要翻三层文件。我的判断标准是——这个部分会不会在别的地方复用?会,就拆。不会,哪怕 500 行也先放着。朋友那个后台有个订单详情卡片,一开始拆了 5 个子组件,后来发现只有这一个页面用,又合并回去了。现在是一个 200 行的组件,读起来反而清楚。 路由和权限这块,动态路由是绕不过去的。但别一上来就搞 router.addRoute 那套。我们先用静态路由把框架搭好,登录后根据角色过滤出可访问的菜单,再用 addRoute 动态挂载。关键点是:路由的 meta 里写清楚 roles: ['admin', 'operator'],导航守卫里统一判断。有个坑要注意——动态添加的路由在刷新后会丢,得在 beforeEach 里判断如果 store.userInfo 为空就重新拉用户信息再挂载。这个逻辑写一次,放在 permission.js 里,别散在 main.js。 构建优化别等到打包 10MB 才做。开发阶段就用 unplugin-vue-components 自动按需引入组件库,路由懒加载是基本操作。有个细节:vite 的 build.rollupOptions 里把 vue、vue-router、pinia 单独拆 chunk,业务代码拆成 vendor 和 app。朋友那个项目优化完,首屏从 4.2s 降到 1.8s。没用什么黑科技,就是把 echarts 和 xlsx 这种大库改成异步加载,用的时候再 import。 最后说个反直觉的:别过度追求目录结构完美。views 下面按业务分文件夹,components 放全局组件,composables 放组合式函数。够了。我见过把 utils 拆成 string、array、date 三个子目录的,结果找个格式化函数翻了四层。项目是给人维护的,不是给架构图看的。 |