最近项目需要将原vue项目结合ts的使用进行改造,这个后面应该是中大型项目的发展趋势,看到一篇不错的入门教程,结合它并进行了一点拓展记录之。本文从安装到vue组件编写进行了说明,适合入门。
1、引入Typescript
| 12
 
 | npm install vue-class-component vue-property-decorator --savenpm install ts-loader typescript tslint tslint-loader tslint-config-standard --save-dev
 
 | 
- vue-class-component:扩展vue支持typescript,将原有的vue语法通过声明的方式来支持ts
- vue-property-decorator:基于vue-class-component扩展更多装饰器
- ts-loader:让webpack能够识别ts文件
- tslint-loader:tslint用来约束文件编码
- tslint-config-standard: tslint 配置 standard风格的约束
2、配置文件
webpack配置
根据项目的不同配置的地方不同,如果是vue cli 3.0创建的项目需要在vue.config.js中配置,如果是3.0以下版本的话,需要webpack.base.conf中配置。(以下说明是在webpack.base.conf文件中更改)
- 在resolve.extensions中增加.ts,目的是在代码中引入ts文件不用写.ts后缀
| 12
 3
 4
 
 | resolve: {extensions: ['.js', '.vue', '.json', '.ts'],
 alias: {}
 }
 
 | 
- 在module.rules中增加ts的rules
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | module: {rules: [
 {
 test: /\.ts$/,
 exclude: /node_modules/,
 enforce: 'pre',
 loader: 'tslint-loader'
 },
 {
 test: /\.tsx?$/,
 loader: 'ts-loader',
 exclude: /node_modules/,
 options: {
 appendTsSuffixTo: [/\.vue$/]
 }
 }
 ]
 }
 
 | 
- tsconfig.json配置
 ts-loader会检索文件中的tsconfig.json.以其中的规则来解析ts文件,详细的配置可以参考https://www.tslang.cn/docs/handbook/tsconfig-json.html
 贴上测试项目tsconfig.json文件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 
 | {
 "compilerOptions": {
 
 "outDir": "./output",
 
 "sourceMap": true,
 
 "strict": false,
 
 "module": "esnext",
 
 "moduleResolution": "node",
 
 "target": "es5",
 
 "allowSyntheticDefaultImports": true,
 
 "isolatedModules": false,
 
 "experimentalDecorators": true,
 
 "emitDecoratorMetadata": true,
 
 "noImplicitAny": false,
 
 "noImplicitReturns": true,
 
 "importHelpers": true,
 
 "listFiles": true,
 
 "removeComments": true,
 "suppressImplicitAnyIndexErrors": true,
 
 "allowJs": true,
 
 "baseUrl": "./",
 
 "paths": {
 "jquery": [
 "node_modules/jquery/dist/jquery"
 ]
 },
 
 "lib": [
 "dom",
 "es2015",
 "es2015.promise"
 ]
 }
 }
 
 | 
- tslint.json配置
 在目录中新增tslint.json文件,由于我们前面安装了tslint-config-standard,所以可以直接用tslint-config-standard中规则,文件如下:
| 12
 3
 4
 5
 6
 
 | {"extends": "tslint-config-standard",
 "globals": {
 "require": true
 }
 }
 
 | 
3、让项目识别.ts
由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在根目录下
| 12
 3
 4
 
 | declare module '*.vue' {import Vue from 'vue';
 export default Vue;
 }
 
 | 
4、vue组件的编写
vue组件里大多数的方法改成通过@xxx(装饰器)来表明当前定义的为什么数据,类似ng中的注入。而业务逻辑js的部分就可以直接采用ts的写法了。
基本写法
模板template和样式style的写法不变,script的模块进行了改变,基本写法如下:
| 12
 3
 4
 5
 6
 7
 
 | <script lang="ts">import { Component, Vue } from "vue-property-decorator";
 @Component
 export default class Test extends Vue {
 
 };
 </script>
 
 | 
- lang="ts":- script张声明下当前的语言是- ts
- @Component:注明此类为一个vue组件
- export default class Test extends Vue: export当前组件类是继承vue的
data()中定义数据
data中的数据由原来的data()方法改成直接在对象中定义
| 12
 3
 4
 
 | export default class Test extends Vue {public message1: string = "heimayu";
 public message2: string = "真好看";
 }
 
 | 
props传值
props的话就没有data那么舒服了,因为他需要使用装饰器了,写法如下
| 12
 3
 4
 5
 
 | @Prop()propA:string
 
 @Prop()
 propB:number
 
 | 
props默认值
| 12
 3
 
 | @Prop({defualt:'abc'
 }) propsA:string
 
 | 
$emit传值
不带参数
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 |   
 
 @Emit('fn')
 bindSend():string{
 return this.message
 }
 
 
 this.$emit('fn',this.message);
 
 | 
方法带参数
| 12
 3
 4
 5
 6
 7
 
 | 
 
 @Emit()
 bindSend(msg:string){
 
 }
 
 | 
emit带参数
| 12
 3
 4
 5
 
 | @Emit('test)
 private bindSend2(){
 
 }
 
 | 
watch观察数据
| 12
 3
 4
 5
 6
 7
 8
 
 | 
 @Watch('propA',{
 deep:true
 })
 test(newValue:string,oldValue:string){
 console.log('propA值改变了' + newValue);
 }
 
 | 
computed计算属性
| 12
 3
 4
 5
 
 | public get computedMsg(){return '这里是计算属性' + this.message;
 }
 public set computedMsg(message:string){
 }
 
 | 
完整代码案例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 
 | <template><div class="test-container">
 {{message}}
 <input type="button" value="点击触发父级方法" @click="bindSend"/>
 <input type="button" value="点击触发父级方法" @click="handleSend"/>
 <input type="button" value="点击触发父级方法" @click="bindSend2"/>
 <!-- <Hello></Hello> -->
 </div>
 </template>
 <script lang="ts">
 import { Component, Prop, Vue, Watch, Emit } from "vue-property-decorator";
 import Hello from "./HelloWorld.vue";
 
 @Component({
 components: {
 Hello
 }
 })
 export default class Test extends Vue {
 
 public message: string = "asd";
 
 @Prop({
 type: Number,
 default: 1,
 required: false
 })
 propA?: number
 @Prop()
 propB:string
 
 public get computedMsg(){
 return '这里是计算属性' + this.message;
 }
 public set computedMsg(message:string){
 }
 
 @Watch('propA',{
 deep:true
 })
 public test(newValue:string,oldValue:string){
 console.log('propA值改变了' + newValue);
 }
 
 @Emit()
 private bindSend():string{
 return this.message
 }
 @Emit()
 private bindSend1(msg:string,love:string){
 
 
 
 }
 
 public handleSend():void {
 this.bindSend1(this.message,'love');
 }
 
 @Emit('test')
 private bindSend2(){
 return '这个可以用test接受';
 }
 }
 </script>
 
 | 
全局混入
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | import Vue from 'vue';
 import { Component, Vue as VueClass } from 'vue-property-decorator';
 import i18n from './lang/i18n';
 @Component
 export default class GlobalMixin extends VueClass {
 public $tt(...args) {
 return i18n(...args)
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 
 | Vue.mixin(GlobalMixin)
 new Vue({
 
 router,
 store,
 render: h => h(App)
 }).$mount("#app");
 
 | 
vue版中的ts报错解决
Require statement not part of import statement.(@typescript-eslint/no-var-requires)
提示报错:
Require statement not part of import statement.(@typescript-eslint/no-var-requires)
解决办法:
.eslintrc.js中的 rules 属性新增以下内容:
  | 12
 3
 4
 
 | rules: {'@typescript-eslint/no-var-requires': 0
 
 }
 
 | 
vue报错Unexpected aliasing of ‘this‘ to local variable @typescript-eslint/no-this-alias
因是在vue中使用_this = this,总是报错Unexpected aliasing of ‘this’ to local variable @typescript-eslint/no-this-alias
原因是 eslint 为了防止this变量和局部变量混淆(大概吧)
解决方法:在.eslintrc.js中的rules添加   “@typescript-eslint/no-this-alias”: [“off”]