最近项目需要将原vue项目结合ts的使用进行改造,这个后面应该是中大型项目的发展趋势,看到一篇不错的入门教程,结合它并进行了一点拓展记录之。本文从安装到vue组件编写进行了说明,适合入门。
1、引入Typescript
1 2
| npm install vue-class-component vue-property-decorator --save npm 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后缀
1 2 3 4
| resolve: { extensions: ['.js', '.vue', '.json', '.ts'], alias: {} }
|
- 在module.rules中增加ts的rules
1 2 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文件
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 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中规则,文件如下:
1 2 3 4 5 6
| { "extends": "tslint-config-standard", "globals": { "require": true } }
|
3、让项目识别.ts
由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在根目录下
1 2 3 4
| declare module '*.vue' { import Vue from 'vue'; export default Vue; }
|
4、vue组件的编写
vue组件里大多数的方法改成通过@xxx(装饰器)来表明当前定义的为什么数据,类似ng中的注入。而业务逻辑js的部分就可以直接采用ts的写法了。
基本写法
模板template
和样式style
的写法不变,script
的模块进行了改变,基本写法如下:
1 2 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()
方法改成直接在对象中定义
1 2 3 4
| export default class Test extends Vue { public message1: string = "heimayu"; public message2: string = "真好看"; }
|
props传值
props的话就没有data那么舒服了,因为他需要使用装饰器了,写法如下
1 2 3 4 5
| @Prop() propA:string
@Prop() propB:number
|
props默认值
1 2 3
| @Prop({ defualt:'abc' }) propsA:string
|
$emit传值
不带参数
1 2 3 4 5 6 7 8 9 10
| @Emit('fn') bindSend():string{ return this.message }
this.$emit('fn',this.message);
|
方法带参数
1 2 3 4 5 6 7
|
@Emit() bindSend(msg:string){ }
|
emit带参数
1 2 3 4 5
| @Emit('test) private bindSend2(){ }
|
watch观察数据
1 2 3 4 5 6 7 8
|
@Watch('propA',{ deep:true }) test(newValue:string,oldValue:string){ console.log('propA值改变了' + newValue); }
|
computed计算属性
1 2 3 4 5
| public get computedMsg(){ return '这里是计算属性' + this.message; } public set computedMsg(message:string){ }
|
完整代码案例
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 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>
|
全局混入
1 2 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) } }
|
1 2 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 属性新增以下内容:
1 2 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”]