友情提示!!!
如下图所示,vue-cli
将在下个版本提供开箱即用的TypeScript
的脚手架. 在你阅读文章前, 请检查Vue官方文档: TypeScript支持.
如果官方已经提供了脚手架, 下面文章就可以不用看了. 去vue-cli开箱一个typescript + vue的模板吧!!!
前言
在Vue2.5
版本的升级中, Vue
已经大大的改进了对于类的支持. 但是目前在Vue
中使用TypeScript
依然需要开发者做一些配置和引入第三方的库(例如官方推荐的vue-class-component
). 本文就是基于vue-cli
初始化项目后, 配置TypeScript
所需要的相关步骤.
本位提供了示例代码 , 读者可以在配置的过程进行比对:master
分支为完整代码;baseConfig
分支提供了TypeScript
的配置;extension-example
为引入了vue-class-component
的代码;
初始化项目
1.使用vue-cli
初始化webpack
模板, 并安装该模板所需要的依赖文件
$ vue init webpack vue-typescript-start
2.使用npm
或cnpm
安装typescript
相关依赖
npm i --save-dev typescript ts-loader
配置TypeScript
修改Webpack配置项
修改目录下build/wepback.base.conf.js
文件
- 修改入口文件为
main.ts
, 并顺便在src/
下将main.js
修改成main.ts
entry: {
app: './src/main.ts'
}
- 在
resolve.extensions
中添加上.ts
后缀(未来引入.ts
就可以不再写后缀了)
resolve: {
extensions: ['.js', '.vue', '.json', '.ts'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
}
- 在
modules>rules
中添加ts-loader
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
}
添加vue-shim.d.ts文件
在src目录下新建一个文件vue-shim.d.ts
, 用于识别单文件vue内的ts代码
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
添加tsconfig.json文件
在项目的根目录下添加tsconfg.json
文件, 该文件描述了该项目是一个TypeScript
项目, ts-loader
将会根据该配置信息进行TypeScript
的编译, 下面是我的配置文件作为参考, 全部的配置参见官方配置文档
{
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"allowJs": true,
"module": "esnext",
"target": "es5",
"moduleResolution": "node",
"isolatedModules": true,
"strictFunctionTypes": false,
"lib": [
"dom",
"es5",
"es6",
"es7",
"es2015.promise"
],
"sourceMap": true,
"pretty": true
}
}
其他修改
- 重命名
src/router/
中的index.js
为index.ts
,src/
下的mian.js
修改为mian.ts
, 并将.vue
文件的引入添加后缀(在)
import App from './App.vue'
- 修改src下的
App.vue
文件中的<script>
语言为ts
<script lang="ts">
- 修改
src/compontents/HelloWorld.vue
代码, 让它变得更清爽和更应主题一点吧!
<template>
<div class="hello">
<h1>{{msg}} </h1>
</div>
</template>
<script lang="ts">
export default {
name: 'HelloWorld',
data () {
return {
msg: '欢迎使用TypeScript + Vue'
}
}
}
</script>
启动TypeScript + Vue的应用
执行npm run dev
, 访问localhost:8080
端口, Vue脚手架启动成功, 现在我们已经成功的在基于vue-cli
创建的项目中, 引入了TypeScript
!
到此处的代码为: baseConfig分支
使用扩展组件
上面已经将TypeScript
集成到了Vue
框架中, 但是到目前为止, 如果想写TypeScript
我们还必须借助一些第三方的类库, 例如前面提到的vue-class-component
和vue-property-decorator
. 也许有读者疑惑为什么要使用这些第三方类库? 我们可以用HelloWorld.vue
组件的代码说明:
<script lang="ts">
export default {
name: 'HelloWorld',
data () {
return {
msg: '欢迎使用TypeScript + Vue'
}
}
}
</script>
其中msg
这个属性显而易见是string
的类型, 按照TypeScript
的写法, 我们理应将其加上类型定义, 所以这一行代码就变成了msg: string: '欢迎使用TypeScript + Vue'
. 这样写既不符合TypeScript
的语法, 也不符合Vue
的语法. 所以一些聪明的开发者, 引入了ES7中的装饰器, 解决了这个问题.
安装依赖
安装vue-class-component
和vue-property-decorator
npm i vue-class-component vue-property-decorator --save
基于vue-class-componet
改写.vue
vue-class-component
提供了@Component
装饰器来抒写.vue
文件. 下面以示例代码说明其用法
- 改写
App.vue
<script lang="ts">
import Vue from 'vue';
import Component from "vue-class-component";
@Component
export default class App extends Vue{
name:string = 'app';
}
</script>
上述就是引入了vue-class-component
的@Component
装饰器后.vue
文件的写法. 你可以看到的是, 我们去掉了data(){ return { ... } }
等函数. 引入@Component
装饰器后, 可以让我们写.vue
组件更加的扁平化. 你也许通过改写App.vue
无法感受到其优点, 那么通过下面的例子, 我相信你会有一种全新的写.vue
文件的体验.
- 改写
HelloWorld.vue
<template>
<div class="hello">
<h1>{{msg}}</h1>
<h3>今年是: {{yearNumber}} 年</h3>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
@Component
export default class HelloWorld extends Vue {
//初始化data
msg: string = "欢迎使用TypeScript + Vue";
user: string = "亲爱的Vuer";
yearNumber: number;
//mounted钩子
mounted(): void {
this.greet(this.user);
}
//created钩子
created(): void {
this.yearNumber = 2018;
}
//methods定义方法
greet(user: string): void {
alert(user + ", 你好!");
}
}
</script>
通过上面的例子, 相信你已经完全体会到了使用vue-class-component
提供的@Component
抒写Vue
代码的简洁. 如果想更多的了解这个库, 可查看官方提供的example
到此处的代码为: extension-example分支
vue-property-decorator
的用法
vue-property-decorator
是一个依赖于vue-class-component
的库, 它在@Component
这个装饰器的基础上新增了6个装饰器, 下面以官方提供的示例代码说明其用法
- 使用了
vue-property-decorator
写.vue
文件
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'
const s = Symbol('baz')
@Component
export class MyComponent extends Vue {
@Emit()
addToCount(n: number){ this.count += n }
@Emit('reset')
resetCount(){ this.count = 0 }
@Inject() foo: string
@Inject('bar') bar: string
@Inject(s) baz: string
@Model('change') checked: boolean
@Prop()
propA: number
@Prop({ default: 'default value' })
propB: string
@Prop([String, Boolean])
propC: string | boolean
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'
@Watch('child')
onChildChanged(val: string, oldVal: string) { }
@Watch('person', { immediate: true, deep: true })
onPersonChanged(val: Person, oldVal: Person) { }
}
- 上面的一段代码等同于下面的常规写法
const s = Symbol('baz')
export const MyComponent = Vue.extend({
name: 'MyComponent',
inject: {
foo: 'foo',
bar: 'bar',
[s]: s
},
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean,
propA: Number,
propB: {
type: String,
default: 'default value'
},
propC: [String, Boolean],
},
data () {
return {
foo: 'foo',
baz: 'bar'
}
},
provide () {
return {
foo: this.foo,
bar: this.baz
}
},
methods: {
addToCount(n){
this.count += n
this.$emit("add-to-count", n)
},
resetCount(){
this.count = 0
this.$emit("reset")
},
onChildChanged(val, oldVal) { },
onPersonChanged(val, oldVal) { }
},
watch: {
'child': {
handler: 'onChildChanged',
immediate: false,
deep: false
},
'person': {
handler: 'onPersonChanged',
immediate: true,
deep: true
}
}
})
示例代码
1. Github仓库
TypeScript相关文档
1. TypeScript入门教程
2. TypeScript官网
参考文章
1. Decorators in ES7: ES7中装饰器
2. ES7 Decorator 装饰者模式
3. vue + typescript 新项目起手式
4. vue + typescript 进阶篇
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。