原始项目,令人头秃
我刚接手手头这个项目的时候,console里到处飘红,整个项目哪哪都是bug,满目疮痍。经过一段时间的调整,虽然可以正常运行,但是很多问题迟迟没有解决,比如乱七八糟的调用、没有闭合的if else、没有处理的try catch……可以说,为了维护这一个问题多多的项目,牺牲了很多我的头发...以上是牢骚段落。
作为一个深知“懒是第一生产力”的工具人,在烦躁之余,一直在寻找一劳永逸的方法。终于,typescript进入我的视线。有了typescipt,一些基础的问题可以直接在编写、编译时报错,它的好处我也不必多说了。
然而,vue+typescript的做法并不普遍,也有争议,网上也多是老版本的做法,对于vue-cli3+typescript,怎么样平滑地、一天做一点地引入typescript呢?
生产力工具篇
vue add typescript
第一步看官网资料,官网详尽地写了如何配置,不过,对于大多数用vue-cli搭建的项目,其实重点是第一句

vue add @vue/typescript
该插件会帮助配置webpack,引入ts.config,并把js文件转换成ts文件,作为参考,还会同时生成一个ts写法的vue文件。

Allow .js files to be compiled
选择yes,允许js编译。
vue-js转换为vue-ts
重构最累的一点就是,为了给类型标注,几乎要把之前的所有文件重写一遍,比如:
import Vue from 'vue'
import Component from 'vue-class-component'
// 1.添加修饰符
@Component()
// 2.基于类的vue文件
export default class MyComponent extends Vue {
// 3.属性标注
message: string = 'Hello!'
// 4.方法标注
onClick (): void {
window.alert(this.message)
}
// 5.其他变化
}
这样修改很难吗?不难,但谁会想做个重复劳动百八十回的工具人呢?
解放双手,自动转换:TransVue2Ts
这里特别感谢 @清液 大神的解放双手-vue语法自动转typescript ,文中提到了转换工具,可以将vue-js的data/computed/prop/watch/mixin等统统转换成vue-ts,我都一一测试过,没有任何问题,强力推荐!👍👍👍
具体的转换方式和写法都在上文帖子中,我就不赘述了。 有了转换工具,完全可以在需要时再将vue-js转为vue-ts,局部重构。
tslint
我用的是腾讯团队的tslint-config-alloy,规则因团队而异,大体按照这套规则。

踩坑篇
引入第三方插件
当在vue中引入第三方的插件时,typescript会无法识别
import '*' as _ from 'lodash'
这时可以先尝试添加官方的typescript类型声明npm install @types/xxx
npm install @types/lodash
像lodash这种,官方是有ts声明文件的,添加后就可以识别了;对于没有声明文件的,则需要在shime-global.d.ts
文件中声明
declare module 'xxx'
data属性无法访问全局属性
解决方案:写在created()钩子中。最常见的例子:
@Component()
export default class Hello extends Vue {
id:string = this.$route.query.id // 这样是会报错的
// 改成这样即可
id:string = ''
created(){
this.id = this.$route.query.id
}
}
对象的undefined、null处理
我们经常会遇到这种情况:
let user= {
name:'小明',
friends:[
{name:'小明的朋友'}
]
}
alert(user.friends[0].name) // '小明的朋友'
当小明不存在(user为null),或者小明没有朋友(friends为null)时,就会报错,解决:
// 方法一
if(user&&user.friends&&user.friends.length>0){
alert(user.friends[0].name)
}
// 方法二
alert((((user||{}).friends||[])[0]||{}).name)
要是再多几层,就会更难写难读,所以我推荐方法三:使用 ts-optchain
import { oc } from 'ts-optchain';
alert(oc(user).friends[0].name('这里可以给个默认值'))
小结
文章仅是我个人的经验总结,也只是提到了重构中关键性的工具,具体配置以官方为准,如有错漏,欢迎批评指正!