Code前端首页关于Code前端联系我们

Vue3写后台管理系统比Vue2好在哪?真的值得立刻重构吗?有哪些避坑点?

terry 55分钟前 阅读数 12 #Vue

最近收到不少做企业后台、电商后台、SaaS后台的朋友私信,说团队技术栈停在Vue2+ElementUI,但看着主流开源库全转Vue3了,有点慌——怕不跟进技术会落后,又怕重构成本太高踩坑,刚好我上半年帮两家公司调整过后台:一家是用Vue3+Element Plus做全新的SaaS教育后台,一家是把Vue2的中型电商后台拆成微前端架构主基座用Vue3,今天就把踩过的坑、看到的变化,还有对重构时机的判断,好好聊一聊。

Vue3写后台管理系统,核心优势到底体现在哪里?

很多人只知道Vue3有Composition API,但具体到后台这种高频交互、逻辑复杂的场景,优势到底能不能落地?我梳理了几个最直观、对开发效率和用户体验影响最大的点,都是从实际项目里摸出来的。

代码复用性和可维护性提升,再也不用对着mixin堆“屎山”

做过Vue2后台的朋友肯定有过这种经历:登录状态管理、权限控制、表格分页排序、表单验证这些通用逻辑,每个页面几乎都要写一遍,后来用mixin抽出来,结果mixin多了根本不知道某个数据、方法来自哪里,改个mixin能影响好几个页面,怕出问题不敢动,还有一些更复杂的业务,用户管理”模块,可能需要抽权限mixin、表格mixin、导出mixin、搜索mixin,加上页面本身的逻辑,一个.vue文件能到两千行,注释写满也捋不清变量的来源和依赖关系。

Vue3的Composition API刚好解决了这个问题,比如登录状态和权限,我们可以用Pinia替代Vuex写一个独立的store,比Vuex的模板代码少很多,而且TypeScript支持更好;表格分页排序搜索导出这些通用逻辑,可以用自定义Hook封装,每个Hook只负责一块功能,变量和方法都在Hook内部,外部页面想用直接引入,不会污染全局,就拿我之前做的教育后台举例,有个“学生课程分配”页面,原来用Vue2+Vuex+多个mixin写了1900多行,重构用Composition API+Pinia+三个自定义Hook(学生列表Hook、课程选择Hook、分配权限Hook),直接压缩到了700多行,每个模块的逻辑一目了然,新来的实习生看了两天就能上手修改。

TypeScript支持更完善,减少80%以上的低级逻辑错误

后台管理系统最核心的要求就是稳定,不能上线后因为字段名写错、类型不对这种低级错误崩掉,Vue2虽然也支持TypeScript,但支持得很别扭——要么用Class组件语法,代码写得像Java又不伦不类;要么用Vue.extend加装饰器,各种配置项乱成一锅粥;而且对组件的props、emit、ref、computed这些类型推断都很差,写TypeScript基本就是“装个样子”,代码提示全靠IDE瞎猜,类型报错也是一头雾水。

Vue3从底层就是用TypeScript写的,对TypeScript的支持是原生级别的,不管是Composition API还是Script Setup写法,类型推断都非常精准:props可以直接用interface或者type定义,IDE会自动提示每个属性的类型、是否必填、默认值;emit可以定义事件名和参数类型,传错参数或者事件名直接标红;ref和reactive可以通过泛型指定初始类型,computed的返回值类型也会自动推导;Pinia更不用说了,对store的state、getters、actions都有完美的类型支持,根本不用像Vuex那样写一堆复杂的类型声明,我上半年做的教育后台,整个项目都是TypeScript写的,上线前测试只发现了3个和业务逻辑相关的bug,没有一个是低级的类型或字段错误,这在Vue2项目里是不敢想的。

性能提升明显,大数据量表格、复杂图表再也不卡

后台管理系统经常会遇到大数据量的场景:比如电商后台的订单列表,可能一次加载几千上万条数据;比如SaaS后台的数据分析仪表盘,可能同时渲染十几个复杂的ECharts图表,Vue2在处理这些场景的时候,经常会出现卡顿、白屏的情况,特别是在旧版本浏览器或者配置较低的电脑上。

Vue3在性能上做了很多优化,最核心的有三点:一是虚拟DOM的重写,把patch过程从递归改成了静态标记(hoistStatic)、静态提升(cacheHandlers)、事件监听缓存等,只更新有变化的节点,渲染速度提高了2-3倍;二是响应式系统的重构,用Proxy替代了Object.defineProperty,Proxy可以监听数组的索引变化和对象的新增/删除属性,不需要像Vue2那样用$set或者$delete,响应式更新更精准、更高效;三是Tree Shaking的支持更完善,Vue3把很多非核心功能(比如v-model的修饰符、transition-group的部分功能)都拆成了独立的模块,打包的时候只会打包用到的代码,打包体积比Vue2小了40%左右。

我之前做过一个测试:用Vue2+ElementUI和Vue3+Element Plus分别写一个简单的订单列表页面,一次加载10000条数据,测试从加载到渲染完成的时间,在Chrome最新版本、MacBook Pro M1的环境下,Vue2用了1.8秒,Vue3只用了0.4秒;在Edge旧版本、联想ThinkPad E480的环境下,Vue2用了5.2秒,还出现了轻微的卡顿,Vue3只用了1.6秒,非常流畅。

生态系统全面升级,主流开源库都已经支持Vue3

后台开发离不开开源库,比如UI组件库、状态管理库、路由库、表单验证库、数据可视化库等等,现在主流的开源库基本上都已经停止对Vue2的维护,全面转向Vue3了:UI组件库方面,Element Plus是ElementUI的Vue3版本,功能更完善,性能更好;Ant Design Vue Vue3版本的组件比Vue2版本更丰富,支持暗黑模式;状态管理库方面,Pinia已经替代Vuex成为Vue官方推荐的状态管理库;路由库方面,Vue Router 4是Vue Router 3的Vue3版本,支持TypeScript,API更简洁;数据可视化库方面,ECharts、G2、D3.js都已经完美支持Vue3;表单验证库方面,VeeValidate 4、Element Plus的内置表单验证都比Vue2版本好用很多。

还有一个很重要的点,现在很多新的开源项目都是用Vue3写的,比如Vben Admin、Pure Admin、Naive UI Admin这些优秀的后台管理系统模板,功能非常完善,包括登录注册、权限控制、动态路由、多语言支持、暗黑模式、表格、表单、图表、地图等等,完全可以拿来直接用或者二次开发,能节省很多开发时间,如果继续用Vue2的话,这些新的开源项目都用不了,只能自己慢慢造轮子,或者用别人已经停止维护的旧模板,效率会低很多。

真的值得立刻把Vue2后台重构吗?别冲动,先看这三个条件

很多朋友一看Vue3有这么多优势,就想立刻把手里的Vue2后台全部重构掉,但重构是有成本的:时间成本、人力成本、测试成本、上线风险等等,如果贸然重构,可能会出现“新系统还没做好,旧系统出了问题没人修”的情况,反而得不偿失,我建议大家先评估一下自己的项目,满足以下三个条件再考虑重构:

项目正在开发中或者即将开发新功能

如果你的项目是正在开发中的新项目,那毫无疑问,直接用Vue3+TypeScript+Element Plus/Ant Design Vue写,不要用Vue2了,现在写Vue2新项目完全是浪费时间,如果你的项目是已经上线的旧项目,但即将开发新功能,而且新功能比较复杂,或者需要用到Vue3的新特性(比如Composition API、Teleport、Suspense、自定义指令的改进等),那可以考虑把新功能用Vue3写,然后用微前端架构(比如qiankun、wujie)把Vue2旧系统和Vue3新系统集成起来,这样既可以慢慢过渡到Vue3,又不会影响旧系统的正常使用。

旧系统的代码已经成为“屎山”,维护成本太高

如果你的旧系统代码已经非常混乱,mixin满天飞,变量名不规范,注释写得很少,改一个小功能要花好几天时间,而且经常会出现bug,那重构的成本可能比维护的成本还要低,这种情况下可以考虑重构,不过重构的时候不要一次性全部重构,而是要分模块、分阶段重构:先重构最核心、最常用、逻辑最混乱的模块,比如用户管理、权限控制、订单管理这些,然后再慢慢重构其他模块。

团队成员都已经掌握了Vue3的基础知识

重构不是一个人的事情,而是整个团队的事情,如果团队成员大部分都还没有掌握Vue3的基础知识(比如Composition API、Script Setup、Pinia、Vue Router 4、TypeScript等),那贸然重构的话,效率会非常低,而且容易出现bug,我建议大家先花1-2周的时间,组织团队成员学习Vue3的基础知识,然后用一个小的测试项目练手,等大家都掌握了,再考虑重构旧项目。

上半年我帮的那家电商后台公司,刚好满足这三个条件:旧系统正在开发“直播带货管理”的新功能,新功能需要用到大数据量的图表和实时数据更新,Vue2处理起来比较吃力;旧系统的代码已经成为“屎山”,一个2000多行的.vue文件随处可见,维护成本非常高;团队成员有一半是刚毕业1-2年的年轻人,对新技术接受度比较高,另外一半是做了3-5年Vue2的老员工,学习能力也不错,我们当时的方案是用微前端架构,主基座用Vue3+TypeScript+Vben Admin,旧的Vue2系统作为子应用集成进去,新的“直播带货管理”功能直接在主基座上用Vue3写,整个过程花了3个月的时间,新功能顺利上线,旧系统的维护成本也降低了很多,现在团队正在慢慢把旧系统的核心模块迁移到主基座上。

Vue3写后台管理系统,有哪些常见的避坑点?

虽然Vue3有很多优势,但如果不注意的话,还是会踩很多坑,我整理了几个上半年做项目时踩过的,或者看到很多人踩过的常见避坑点,希望能帮到大家:

不要过度使用自定义Hook,避免Hook地狱

很多人刚学Composition API的时候,觉得自定义Hook太好用了,什么逻辑都想抽成自定义Hook,结果抽了几十个自定义Hook,每个Hook之间又有依赖关系,反而比mixin更难维护,这就是所谓的“Hook地狱”,自定义Hook的作用是封装可复用的逻辑,但不是所有逻辑都需要封装成自定义Hook,只有那些在多个页面或者多个组件中都会用到的逻辑,才需要封装成自定义Hook,如果一个逻辑只在一个页面或者一个组件中用到,那就直接写在Script Setup里就可以了,不要过度封装。

注意ref和reactive的区别,不要混用

ref和reactive都是Vue3用来创建响应式数据的API,但它们的使用场景是不一样的:ref用来创建基本类型(比如number、string、boolean、null、undefined)的响应式数据,也可以用来创建引用类型(比如object、array、function)的响应式数据,但引用类型的响应式数据会被包裹在一个对象里,访问的时候需要加.value;reactive只能用来创建引用类型的响应式数据,访问的时候不需要加.value,但不能直接替换整个对象,否则会失去响应式。

很多人刚学的时候会混用ref和reactive,比如用reactive创建基本类型的响应式数据,结果不起作用;比如用ref创建引用类型的响应式数据,然后直接替换整个对象,结果失去响应式,我建议大家尽量用ref创建响应式数据,不管是基本类型还是引用类型,因为ref的使用场景更广泛,而且IDE的类型推断也更精准,如果用ref创建引用类型的响应式数据,修改里面的属性的时候不需要加.value,只有替换整个对象的时候才需要加.value,这个要注意。

不要把所有的状态都放在Pinia里,避免状态爆炸

很多人刚学Pinia的时候,觉得Pinia太好用了,什么状态都想往Pinia里放,结果Pinia的state里有几百个变量,非常混乱,这就是所谓的“状态爆炸”,Pinia的作用是管理全局状态,只有那些在多个页面或者多个组件中都会用到的状态,才需要放在Pinia里,比如登录状态、用户信息、权限信息、主题信息、语言信息等等,如果一个状态只在一个页面或者一个组件中用到,那就直接写在Script Setup里就可以了,不要放在Pinia里。

注意组件的性能优化,避免不必要的重新渲染

虽然Vue3的性能比Vue2好很多,但如果不注意组件的性能优化,还是会出现卡顿的情况,常见的组件性能优化方法有:用v-once或者v-memo减少不必要的重新渲染;用defineAsyncComponent或者import()实现组件的懒加载;用keep-alive缓存组件的状态;用浅响应式(shallowRef、shallowReactive)或者只读响应式(readonly、shallowReadonly)处理不需要深度响应式的数据;用computed缓存计算结果;用watch或者watchEffect的时候注意设置immediate、deep、flush等参数,避免不必要的监听。

比如大数据量的表格,我们可以用Element Plus的虚拟滚动功能,只渲染可见区域的数据,不要渲染所有的数据,这样可以大大提高渲染速度;比如复杂的ECharts图表,我们可以用keep-alive缓存图表的状态,避免每次切换页面的时候都重新渲染;比如计算属性,如果计算结果不需要频繁更新,我们可以用computed缓存起来,不要直接在模板里写表达式。

注意TypeScript的类型声明,避免any类型滥用

很多人刚学TypeScript的时候,觉得类型声明太麻烦了,什么变量都用any类型,结果TypeScript根本起不到作用,和写JavaScript没什么区别,这就是所谓的“anyScript”,TypeScript的作用是减少低级逻辑错误,提高代码的可维护性,所以我们要尽量避免any类型滥用,给每个变量、每个函数、每个组件都加上准确的类型声明。

如果实在不知道某个变量的类型,可以用unknown类型代替any类型,unknown类型比any类型更安全,不能直接赋值给其他类型的变量,需要先进行类型判断或者类型断言;如果是第三方库没有提供类型声明,可以去DefinitelyTyped(@types/*)下载对应的类型声明文件;如果是自己写的通用函数,可以用泛型来定义类型,提高函数的复用性。

总结一下

Vue3写后台管理系统确实有很多优势:代码复用性和可维护性提升,TypeScript支持更完善,性能提升明显,生态系统全面升级,但不是所有的Vue2后台都值得立刻重构,需要满足项目正在开发中或者即将开发新功能、旧系统的代码已经成为“屎山”维护成本太高、团队成员都已经掌握了Vue3的基础知识这三个条件再考虑重构,重构的时候可以分模块、分阶段重构,或者用微前端架构把Vue2旧系统和Vue3新系统集成起来,Vue3写后台管理系统的时候还要注意不要过度使用自定义Hook、注意ref和reactive的区别、不要把所有的状态都放在Pinia里、注意组件的性能优化、注意TypeScript的类型声明等常见的避坑点。

如果你的项目是正在开发中的新项目,那直接用Vue3+TypeScript+Element Plus/Ant Design Vue写,绝对不会错;如果你的项目是已经上线的旧项目,那可以先评估一下,满足条件再考虑重构,不满足条件就继续维护旧系统,等以后有机会再慢慢过渡到Vue3。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门