TypeScript在Vue项目中使用
前言
近两年来,TypeScript 的发展势头很猛。其实Vue官方从2.6.X版本开始就部分使用TypeScript重写了。而且根据 Evan You 发布的 Vue 3.0 计划,Vue 3.0 将完全使用 TypeScript 重写。说白了TypeScript还是很有前景的,那么作为一名热爱学习的程序员上手撸它就对了。
哎呀妈,真香。。。
TypeScript 是什么
TypeScript = Type + Script(标准JS)。我们从TS的官方网站上就能看到定义:TypeScript is a typed superset of JavaScript that compiles to plain JavaScript。TypeScript是JavaScript类型超集,他可以编译成纯的JavaScript。
最初,JavaScript 是一个为了浏览器而设计的语言,可以提供一些基础的用户交互。JS本身作为一个弱类型语言,在开发过程中有极大的灵活性,可能也正是这种灵活性,使得更多的开发人员接受这个在创始之初不被看好的语言。
随着最近几年,JavaScript的飞速发展。nodejs的出现,使得JS不在局限于浏览器中。而且随着单页面应用的流行,使得前端逐渐迈向工程化,项目也越来越庞大。那随之而来的问题就是松散的代码、乱七八糟的类型使的项目的越来越难以维护、被人写的代码难以难以读懂、稳定性差等问题也随之暴露出来。
TypeScript 有什么用?
- TypeScript使代码更容易阅读和理解,有了类型系统的规范,每个方法的入参反参都会有一定的约束,正是这些约束使得代码更加容易阅读和理解。
- 可维护性更好,长期迭代维护的项目开发和维护的成员会有很多,团队成员水平会有差异,在长期维护的过程中代码质量会慢慢降低,在强类型约束和静态检查,以及智能IDE的帮助下,提升可维护性。
- TypeScript是类型系统,而且是JavaScript的超集。JavaScript能做的TypeScript都可以做,JavaScript做不到的TypeScript也可以做到。
- TypeScript已经相对成熟了,网上的资料也很齐全,大部分的库和框架都对TypeScript做了很好支持
- VSCode、WS等IDE对TypeScript的支持相当好,有智能提示,有智能感知bug。
- 静态类型检查可以让我们的bug尽可能消灭在编译器,加上现代IDE有智能纠错,编码时就能提前感知bug的存在。
Vue组件的Ts写法
从零搭建一个Ts-vue项目
- 安装官方脚手架
npm install -g @vue/cli
# OR
yarn global add @vue/cli
- 执行创建项目的命令
vue create map-ts
- 选择配置项
然后,命令行会要求选择预设。使用箭头键选择Manually select features。
接下来就是你想要的配置了,当然如果创建的是ts项目的话TypeScript和Babel选项是必选的
然后就是一步步选择你的配置项目了,我的是这个样子的,如下图
接着等待项目初始化完成,就是下边这个样子的
- 最后启动项目
yarn serve
#or
npm run sercve
vue-property-decorator
这里单页面组件的书写采用的是 vue-property-decorator 库,该库完全依赖于 vue-class-component ,也是 vue 官方推荐的库。
单页面组件中,在 @Component({}) 里面写 props、data 等调用起来极其不方便,而 vue-property-decorator里面包含了 8 个装饰符则解决了此类问题,他们分别为:
@Emit 指定事件emit,可以使用此修饰符,也可以直接使用 this.$emit()
@Inject 指定依赖注入
@Mixins mixin 注入
@Model 指定 model
@Prop 指定 Prop
@Provide 指定 Provide
@Watch 指定 Watch
@Component export from vue-class-component
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
class Person {}
@Component
export default class Map extends Vue {
mapData: string = ''
count = 0;
person: Person = {}
// Prop
@Prop({default: 0}) private prop1 !: number;
@Prop({ default: () => [10, 20, 30, 50] }) private prop2!: number[]
// watcher
@Watch('person', { immediate: true, deep: true })
onPersonChanged (val: Person, oldVal: Person) {}
// 生命周期
private created ():void { },
private mounted ():void { },
private updated ():void { },
private destroyed ():void { }
}
其他修饰符详情请参考vue-property-decorator这里就不一一列举了
一个Vue组件
下面是一个地图组件示例
<template>
<div>
<h1 class="header">{{ reversedMessage }}</h1>
<div class="map" id="mapContainer"></div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import {getDataViz} from '@/api/dataViz'
@Component
export default class Map extends Vue {
map: any;
message = 'yeHoeG';
// 计算属性(虽然没有必要,但是我想用一下)
private get reversedMessage (){
return this.message.split('').reverse().join('')
}
private async mounted () {
// 初始化地图
this.initMap()
// 显示底图
this.addTileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
cluster: ['a', 'b', 'c']
})
// 发送可视化请求
const vizId = await this.dataViz();
// 加载瓦片
this.addTileLayer(`http://geohey.com/s/dataviz/${vizId}/{z}/{x}/{y}.png?retina={i}&ak=MWRiZjhkYjRhNmNjNGZmYThiNzQzYjU0MWQ1MjE4YWM`, {
crossOrigin: ''
})
}
// 初始化地图
initMap() {
this.map = new this.$G.Map('mapContainer', {
maxRes: 19567.879241,
recordStatus: false,
pinchRotate: false,
continuouslyZoom: false,
zoomDelta: 1,
hideLogo: true,
initStatus: {
pitch: 10,
center:[11791655.063735005, 4563584.047148498],
res: 4891.96981025
}
});
}
// 获取dataViz
async dataViz(): Promise<string> {
let result: any;
try {
result = await getDataViz();
} catch (err) {
console.error(err)
}
if(result && result.code !== 0) {
console.error(result)
}
return result.data.vizId
}
// 添加 瓦片图层
addTileLayer(url: string, data: any) {
const tileLayer = new this.$G.Layer.Tile(url, {
...data
});
tileLayer.addTo(this.map);
}
}
</script>
结果如下图:
哈哈,一个TS-Vue组件就是这么简单
总结
在刚开始用TS写组件的时候,真的是特别不适应,被它的类型检查搞得有点烦躁,但是慢慢的一个组件写下来之后,发现TS的类型检查在编译的时候就帮我避免了很多bug。
在有JS的基础下,TS的学习成本不高,但是TS和一些框架一起使用的时候还是或多或少的有一些坑存在的。
没有最好的,只有最适合自己的,到底用不用TS,还是要看实际项目规模、项目生命周期、团队规模、团队成员情况等实际情况综合考虑。