2021年到了,Vue 3准备好了吗?

      ☕ 5 分钟
Vue 3 图/v3.cn.vuejs.org
Vue 3 图/v3.cn.vuejs.org

经历了两年多的开发,Vue 3.0终于在2020年9月18日发布。2021年年初,我抱着尝鲜的想法用Vue 3及其生态编写了一个企业应用的管理后台,两个人断断续续做了一个月后项目上线。

先说结论,综合我的经历,我认为Vue 3及其生态已经生产可用并且好用,对比Vue 2,API的变化并不大。

Vue 3及其生态

我负责的管理后台项目和大部分的企业应用管理后台一样,前后端分离,前端通过HTTP API和后端通信,有路由、大量的列表、筛选新增编辑删除,按字段类型不同,需要不同的表单组件。

我用到了这些和Vue 3生态相关的东西:

  • Vue 3
  • Typescript + vue-class-component:Vue 3本身是用Typescript实现的,但是要想让使用Typescript的体验更流畅,vue-class-component不可少;
  • Vue Router:路由;
  • Vuex:状态管理和可观测性,应用有一定规模后几乎是必选;
  • Element Plus:功能齐全的组件库,Vue 3版本的用下来基本上没有坑。

Element Plus是Element的Vue 3版本,用来开发管理后台表单速度杠杠的,但是它对Vue的新版脚手架工具Vite的适配还不太好,所以我使用Vue CLI进行了初始化。根据你的选择,脚手架会可以为你准备好上面的全部东西。

不过,截止2021年3月,Vue 3的生态还不是尽善尽美:

  • 脚手架未必会使用最新的版本,所有初始化完成后最好到package.json里检查一下各个依赖的版本;
  • vue-class-component匹配Vue 3的v8版本还没有正式的文档,遇到问题你得去翻它的Github仓库的Issue(┑( ̄Д  ̄)┍),用下来觉得它的功能是做完了,体验不错,就是没有文档这事比较拉跨;
  • 原来用来调试Vue应用的官方Chrome扩展还没有支持Vue 3,官方出了一个处于Beta阶段,只支持Vue 3的新版本,暂时只能检查Component,看不了Store里的东西,而且因为是Beta版本,它自己会往控制台里吐不少日志……

Vue 3 API的变化

和Vue 2比起来,Vue 3的API变化很少,团队迁移成本不算高,我认为变化最明显的是下面这些。

Typescript

一般来说,项目体量越大,功能和数据结构越复杂就越推荐Typescript,它能将不少运行时错误提前到编译时发现,同时类型系统对构建复杂应用很有帮助。

Vue 2&3都使用vue-class-component来提升Typescript的开发体验,Vue 3对应的vue-class-component的v8版本改动还是有些大的,好在改动主要在写法上而不是概念上。如果团队本来就熟悉使用Typescript开发Vue 2项目,基本上在几小时后就能适应这些变化。

Reactive API

Vue 3新增了Reactive API,作用有些像Vue 2的Vue.set(),用来显式地声明要进行响应性跟踪的目标。将这个API暴露出来确实让框架的思路更清晰,学习成本也不高,但是还是让我有过一些困惑:

  • 如果你在使用store,你会发现你有时候根本用不上它(特别是reactive()ref());
  • 使用Typescript + vue-class-component,声明组件内部的属性时,你也用不上它;
  • 有了上面这两个“例外”后,你有时就会纠结,在“这里”用reactive()ref()是对的吗?

我在Vue 3里进行了十几个小时的开发工作(以及间或的碰壁和调试)后,才基本缕清了Reactive API的适用情况。

Vue 3在实现上使用Javascript Proxy来监听变量的变动,并在浏览器不支持的情况下退化到Vue 2使用的getter/setter.

Composition API

Composition API,或者叫组合式API,是Vue 3的一大亮点,它是对数据操作(API调用、生命周期钩子对应的函数、watch对应的函数等)的组件化,解决了几个问题:

  • 把同一个语义下的数据操作写到了一起(称为composable),并且可以跨组件复用:比如,用户列表的增删改查,以及进入用户列表时被生命周期钩子触发拉取数据的操作现在可以跨组件复用了;
  • 弥合了store和component的割裂:过去单独使用Vuex的时候,你需要在每个使用store的地方进行从store到component的数据和操作绑定,虽然Vuex提供了mapState()/mapGetter()这些便利化方法,但是无谓的重复还是很让人痛苦。现在,在Composition API这一层做一次绑定工作之后,你在不同的component中都可以复用它。

有意思的是,因为Composition API也可以实现store的数据共享功能,在一定程度上可以替代store,特别是现在Vue 3的Chrome插件在功能上还不能观测store及其操作,使用store并没有带来可观测性上的优势,导致每次我在实现store module时都有些怀疑人生……

不过,Composition API也带来了新的易错点,如果你在composable中watch()store中的状态,并且在同一个view中的多个组件中都用了该composable,那么watch()及其回调会被调用多次,这往往不是你想要的效果。解决方案是为composable提供初始化参数。

其他

还有两个小变更值得提下:

  • Component不再强制要求一个根元素;
  • 实现v-model的prop名称(value -> modelValue)和事件名字(input -> update:modelValue)变了。

结语

Vue 3是一个优秀的前端框架,比起Vue 2,它更适合开发大规模或者复杂的Web应用。在成百上千的开发者的努力和贡献下,Vue 3及其生态已经生产可用,如果你正在纠结你的新项目该使用Vue 2还是Vue 3,我推荐你优先考虑Vue 3.

目前官方正在开发一个和Vue 2兼容的Vue 3,该版本的行为与Vue 2兼容,运行时警告不兼容,如果你有重要或者复杂的应用正考虑迁移,你也许应该等待这个版本。

(感谢V2EX网友shakukansp指出文章中的表述问题)


nanmu42
作者
nanmu42
用心构建美好事物。

目录