TypeScript在Vue2.x中的坑
# # TypeScript在Vue2.x中的坑
TypeScript是JS的超集,笔者非常建议在大型系统中使用TypeScript,因为它的类型系统使得代码可维护性提高了许多。但由于Vue2.x版本有设计断层,导致很多类型是通过declare方式推导出,而不是基于class的API,这也是为什么Vue3.0用typescript重写的原因之一。在期待Vue3.0的同时,来聊下在Vue2.x中使用TypeScript的一些坑。
# # 1. 扩展Vue全局方法复杂
增加Vue全局方法,需要在'vue/types/vue'模块下扩展,十分突兀。
// 1. 确保在声明补充的类型之前导入 'vue'
// 保证是在Vue模块下,使得不影响以前的Vue模块
import Vue from 'vue'
// 2. 定制一个文件,设置你想要补充的类型
// 在 types/vue.d.ts 里 Vue 有构造函数类型
declare module 'vue/types/vue' {
// 3. 声明为 Vue 补充的东西
interface Vue {
$myProperty: string
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# # 2. 全局mixin this问题
由于Vue有设计断层,所以this问题很苦恼。表现在全局mixin时,由于没有mixin类型,所以当单独抽取出globalMixin变量时,方法中this.$router会报错。
// bad
const globalMixin = {
methods: {
$natigateTo(path: string, params?: any): void {
// this.$router will throw error
this.$router.push(withCluster)
}
}
}
Vue.mixin(globalMixin)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// good for 2.x
Vue.mixin({
methods: {
$natigateTo(path: string, params?: any): void {
this.$router.push(withCluster)
}
}
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# # 3. 装饰器 this !== target 问题
正常的Class在加装饰器的时候使用method.apply(target, args)是没有问题的。但是vue在注册组件的时候会进行初始化,this在这个时候被改变了(class内部的的this变了,此时 this !== target了)
const log = (target, name, descriptor) => {
const method = descriptor.value
descriptor.value = function(...args) {
console.log(`你点击了 ${name} 方法`)
method.apply(target, args)
}
return descriptor
}
@Component
export default class Home extends Vue {
@State jobId: string
@Mutation('SET_JOB_ID') setJobId: (jobid: string) => void
@log
startDashboard(row: JobItem): void {
let { jobId } = row
// below will throw error:
// "TypeError: this.setJobId is not a function"
// because now this !== target
this.setJobId(jobId)
console.log(this.jobId)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# # 参考文章
编辑 (opens new window)