关于vue3+ts在实践中的一些分享

2,048 阅读7分钟

我认为现在是写最这篇文章最好的时刻了。

写在前面

有输入,有沉淀,才有分享。
在过去的四个月中,我全身心投入到一个综合平台的前端开发上,该项目采用的是我搭建的 vue3 基础代码框架(说实话,一开始我也怕到处都是坑...),而这个基础代码库(仓库地址)现在在github上已经收获了 100+ star 了,得到了一些伙伴的肯定与帮助;另外,基于此代码框架的一个中等业务量的综合平台以及后台系统都已经稳定运行在测试环境中,即将发布正式环境(可算是没白摸鱼...);加上我自身间接性的拖延厌恶症(游戏耍腻了),于是便想记录一下这段时间的感想,因此,我认为现在是写这篇文章最好的时刻了。

当然,我的表述中也许还有不足和错误,烦请指出。

vue3 现状

vue3 相对于vue2的好处不再介绍,更好的响应式、函数式、模版编译优化等等...但是大多数还未上手或者处于观望状态的伙伴多是有以下的疑问——vue3 现在哪个版本了?坑还多吗?周边生态支持得怎么样?TypeScript支持度以及使用丝滑度怎样?存在浏览器兼容问题吗?Options Api 和 Composition Api 又如何抉择?

就以上问题,根据个人这段时间开发感受而言,可以简略回答为:距离vue3第一个正式版本One Piece发布将近四个月了,这中间差不多每个月有一次bug修复的小版本更新(极少的功能新增),api 已经稳定,没有遇见不可解决的坑,相关的配套 UI 库类似 ant-design-vue、element-plus、vant、taro 都已经支持 vue3,虽然这其中某些库部分功能仍有 bug,但相关组织开发人员都以肉眼可见的速度每天在修复。相关工具正在完善中,有一部分已经可用,如 vue-devtools。

vue3常见业务的基于 composition api 的工具库都已完善。至于兼容低版本浏览的pollify还未出来,如果有这方面需求,则不应该上 vue3。vue3 就是 ts 开发的,因此支持度很好,使用起来非常流畅,在vuex4中 ts比之前支持更好,但还是不够,vuex5 会解决这个问题。因为更好的逻辑复用,使用Composition Api 是趋势所在。

如何快速上手

根据我的使用体验,vue3 跟 vue2 在使用姿势上,除了多了composition api 写法之外,其他并无多大改动。因此,建议主要看这几部分的内容

如何搭建 vue3 基础代码框架

现在,我就以搭建一个基于 vue3+ant-design-vue+ts 为例,初步梳理一下如何搭建 vue3 基础代码框架,搭建出来结果如github.com/ibwei/vue3-…所示,如果对您有帮助的话,可以 star 一下。

主要用到的库

  • vue 全家桶 vue3 + vue-router + vuex + typescript
  • http 请求:axios
  • ui 库:ant-design-vue
  • 提交规范:git cz commitizen
  • 版本更改历史: changelog
  • 文档工具:typedoc
  • 代码检查:eslint+eslint-typescript,格式化:prettier.提交之前检查与修复:lint-staged
  • 测试用例:mocha,ts-node
  • webpack 插件:style-resources-loader(全局 less)webpack-bundle-analyzer(包分析工具) splitChunks(代码分离)

以上库的配置以及使用不再细说,均在代码中有注释。

为了更好利用 vue-cli 开箱即用的便利,我们使用vue-cli生成基础代码。然后,我们先对默认模版进行基础改造,将文件夹目录大致分为如下图所示

下面,列举其中我做了哪些优化

  • 自动装载ES 模块 利用 webpack 的require.context功能,极大便利了我们加载相同功能的 ES 模块,例如批量加载 vuex 子 module,加载路由,加载全局组件,加载插件,只需要类似下面这样简单处理一下即可。

  • TypeScript让Vuex更好用 前面说到,vuex-next 也就是现在 vuex4对 ts 支持并不是完全支持,它支持对 store 对象的type 检查,但是暂时无法做到对 dispatch 以及 getter 的参数做校验,特别是对子module 的校验,因此特意封装了两个工具函数,以此加强对 vuex 的支持。
/**
 * @description setStoreState -方法是一个 mutaitions 的操作
 * @type {T} T - 你要更改的模块的类型
 * @param {string}  module - 要操作的state 的 module 名
 * @param {string}  key - 要操作的state 的 module 下的 key 值
 * @param {any} value - 当有 msg 参数时,视为赋值操作,触发 mutation,msg 则为要复制的数据.
 * @example 如果需要更改 app 模块下的 theme为 dark,这样使用:setStoreState('app','theme','dark')
 * @example 目前只支持更改 module 的 state 第一层,不支持单独修改深层嵌套的 key,如需更改,请直接替换第一层的对象
 *  如
 *   ``` const state = {
 *                 name: {
 *                   firstName:'jack',
 *                   lastName:'Ma'
 *                 }
 *               }
 *   ```
 *  想要单独修改 firstName,直接使用 setStoreState<AppStateType>('app','name',{firstName:'modifiedName',lastName:'Ma'})
 */

export function setStoreState<T>(
  module: ModuleNameType,
  key: keyof T,
  value: any
) {
  store.commit({
    type: module + '/__set',
    key: key,
    val: value
  })
}

/**
 * @description 封装 dispatch 方法
 * @type {T} T  你要派发actions的模块的类型
 * @example 使用方法如下  const result = await dispatchActions<UserActionsType>('console','refreshToken',1)
 */
export async function dispatchAction<T>(
  module: ModuleNameType,
  key: keyof T,
  value?: any
): Promise<any> {
  await store.dispatch(`${module}/${key}`, value)
  Promise.resolve(0)
}
  • 如何使用 typeof 和 keyof 减少人工定义类型 以定义 vuex 子 module举例,如图

并不是每个数据都需要我们先去定义好数据类型,善用ts函数可以节约很多不必要的操作,类似函数还有 keyof,ReturnType,另外有一点建议就是, 某些场景不要排斥 any,善用类型推断。

  • 业务配置、打包环境配置、部署环境配置都得分离

    env.** 放置跟部署环境相关的配置,打包环境配置在 vue.config.js里面配置,业务相关的静态配置其他常规文件夹下。

  • 线上环境选择合适的dev-tool和屏蔽不必要的控制台消息,以保证效率和安全。

  • ToC项目不管走不走oss,都应该适当地做代码分离,以保证用户体验,路由的代码分离在路由配置时做。

  • vue3 的 vue-router 和 vuex 和之前并没有什么变化,只不过是从挂载到原型上变成函数式api 了,在组件中通过 provide 和 inject 使用,但提示支持得更好。

  • 语言国际话方案

    主要是统一三个命名的协同问题,可以查看我的另一篇文章=>十分钟入门前端最佳的语言国际化方案

  • 不要写那么多 mutation

    让 vuex 变得简单起来,请看=>分享一个Vuex的使用的新姿势

  • 提前规划好页面布局以及多种布局切换方案

    本来想就这一块多说一点,但是还是得结合具体业务来说。总之,对于复杂的业务,业务布局是很多的,需要提前规划好,如何切换,状态如何保存。

  • 想说很多,都忘记了,后面再更...

在实践中的一些心得

我差不多就是看了几篇文档,然后折腾了一下基础代码框架,就这样无缝衔接了过来,现在来看,vue3 最难的不是那些新出现的 api,而是如何写好 composition api,如何去抽离这代码逻辑以达到复用的目的,不至于让代码显得是面条,而我自己,也在这一块持续摸索中,对于一开始在项目中使用 vue3 的人,很容易和我一样在不知不觉中一个文件就写了几百行代码,这让一切看起来很糟糕,并没有领会到composition api 这其中的精髓所在。

夜深了,晚点更。

未来

如果2021年了,你还没用上 TypeScript,我真希望你能早点发现它带来的美好。