Vue2项目引入Typescript记录

1,496 阅读5分钟

一、背景以及闲扯

    前段时间去阿里面试,他们所使用的技术栈是react+ts。而个人所在项目使用的是Vue2,面试官的一句“我就不明白了,现在都支持混编,为什么不使用ts呢?”在我脑海中反复回荡,于是我便开始尝试将ts引入当前的项目中。为了不坑组内成员,我需要在引入之前找到以下问题的答案(笔者仅仅学习了1个多月而已,下文也只是个人的见解,如果有什么错误,希望大家及时指正):
(1)是否具有引入的价值(开发效率、编码出错率等)。
(2)是否增加组员额外负担(学习成本,抵触情绪等)。
(3)如何渐进式引入,直接大规模引入必然会引发问题。
(4)如果后续升级到Vue3(公司内部要求不断更新框架版本),改动工作量大小。
(5)使用总结。

二、是否具有引入的价值

    “TypeScript is an open-source language which builds on JavaScript, one of the world’s most used tools, by adding static type definitions.Writing types can be optional in TypeScript, because type inference allows you to get a lot of power without writing additional code.”,ts是门静态类型的语言,并且提供了类型推断。

1、开发效率

    刚开始使用的使用,个人的开发效率必然会有所下降,因为要不断的定义接口类型考虑类型。记得当年刚学习javascript的时候,觉得弱动态类型真是太方便了,一个var就可以直接定义变量,不像java那样还要顾虑到各种类型,于是选择了做前端(-,-)。但使用习惯之后,效率并不会受到很大的影响,而且个人认为,工作量最大的并不是开发阶段,而且是维护定位问题的阶段。

2、编码出错率

    这是引入ts的核心价值了,可以让很多错误在编码的时候就及时发下。当前的项目笔者从零就开始参与,至今已经一年半了,发现大家最大的工作量不在开发,而是出问题之后的定位,问题一旦流到下游,中间的沟通、定位、邮件、扯皮、甩锅就特别耗时。于是笔者分析了这一年半的所有前端问题,发现了很多可以在引入ts之后,在开发阶段就直接发现的问题。如会有大量的a.b.c,但是a.b是undefined的情况,代码就直接报错了。

3、结论

    ts值得引入。

三、是否增加组员额外负担

    当前项目进度十分紧张,团队成员已经十分辛苦,所以个人主观上并不喜欢无故增加他人的工作负担。
(1)学习成本:个人认为要想直接使用ts的话,学习成本并不是很高。就像javascript一样,里面有非常多细节,但是开发过程中并不需要对其特别了解,依旧可以正常开发,ts也是一样的。成员遇到问题需要你第一时间帮其解答,这无疑会增加推动人的工作量,不过这也无可厚非。
(2)抵触情绪:这是增加工作量相关的,这需要让成员明白学习ts其实对自己是有益的。比如大厂面试所需要该技能,对自身以后的发展有所帮助。开展相关培训,让大家先了解ts。从笔者实践来看,大家写js也写无聊了,对于ts的引入并没有太大的抵触,这需要根据实际团队氛围来判断。

四、如何渐进式引入

1、引入原则

(1)原有页面保持不变,新起页面使用ts。
(2)单独js文件优先变更。
(3)公共独立模块优先变更,笔者项目中包含了一个自研的Vue扩展组件,采用Vue.use的方式引入。主要是为了解决iView的问题以及符合前端规范。优先将其变更为ts。
(4)优先变更不常出错的模块文件。

2、编码规范

    并没有重新引入tslint,因为eslint同时支持扫描js、ts。详情见:在Vue2项目中引入typescript流程

五、如果后续升级到Vue3,改动工作量大小

    Vue2使用ts的方式为vue-class-component或者vue.extend({...})的方式。Vue3也是支持vue-class-component的方式(当前最新脚手架生成后,默认使用方式),但是官网推荐的是使用defineComponent的方式使用。

1、使用方式对比

(1)Vue2

import Vue from 'vue';

export default Vue.extend({
	...
})

(2)Vue3

import {defineComponent} from 'vue'

export default defineComponent({
	...
})

    可以看到,如果更新到Vue3,并不会造成很大的改动。使用vue-class-component的方式则没有改动。

2、类型使用

    在使用过程中有时候需要引入Vue的类型,Vue2中的所有类型都在node_modules/vue/types中,可以直接引入。而Vue3则比较复杂,需要在node_modules/@vue中寻找。

六、使用总结

(1)尽量避免使用any,因为这就失去了使用ts的意义。对于一些第三方的类型,可以去node_modules下的源码中去寻找吗,一般会在xxx.d.ts文件中。如node_modules/vue/types/vue.d.ts、node_modules/axios/index.d.ts。
(2)computed下需要定义类型,不然会报错。
错误:

computed: {
  data: {
    get(){
    	return this.dataProps;
    },
    set(value){
    	this.$emit(`on-change`, value);
    }
  }
}

正确:

computed: {
  data: {
  get(): string{
    	return this.dataProps;
    },
    set(value: string){
    	this.$emit(`on-change`, value);
    }
  }
}

(3)Vue下添加变量接口。有时会将框架或组件封装到this下,如axios封装成this.http.get。不做任何配置的情况,ts无法检测到http.get。不做任何配置的情况,ts无法检测到http。这需要在src目下添加shims-vue.d.ts文件。

shims-vue.d.ts

declare module 'vue/types/vue' {
  interface Vue {
  	$http: xxx, // 类型
  }
}

(4)继承类型,笔者曾经扩展过XMLHttpRequest类型,如何在Vue项目中添加接口监听遮罩

interface NewXhrInterface extends XMLHttpRequest{
	requestUrl?: string
}