ts基础类型:查阅最全面的官方API文档(https://www.tslang.cn/docs/handbook/basic-types.html)
re-ts git地址:https://git.jd.com/yuwenbinjie/re-ts
一、项目中接入typescript的好处
- javascript本身属于弱类型,使用起来比较灵活,所以当前端项目多人协作开发时对接成本较高;
- js中参数类型没有校验,也没有规范的接口文档,需要从业务代码上下文中读取
所以在项目中引入ts可以增加代码可读性,减少对接成本,利于工程标准化。
二、在vue-cli2.x项目中接入typescript,不推荐在原有项目上修改
- 安装ts环境依赖:npm i typescript ts-loader@^3.5.0 --save-dev;
- 配置webpack,修改./build/webpack.base.conf.js配置文件:
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 | //entry入口文件main.js改为main.ts: entry: { app: './src/main.ts' } //resolve.extensions添加.ts: resolve: { extensions: [ '.js' , '.ts' , '.vue' , '.json' ] } //module.rules添加.ts解析规则: module: { rules: [ { test: /\.ts?$/, loader: 'ts-loader' , exclude: /node_modules/, options: { appendTsSuffixTo: [/\.vue$/] } } ] } |
-
在项目根目录下建立TypeScript配置文件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 | { "compilerOptions" : { "allowUnreachableCode" : true , // 不报告执行不到的代码错误。 "allowUnusedLabels" : false , // 不报告未使用的标签错误 "alwaysStrict" : false , // 以严格模式解析并为每个源文件生成 "use strict"语句 "baseUrl" : "." , // 工作根目录 "experimentalDecorators" : true , // 启用实验性的ES装饰器 "jsx" : "react" , // 在 .tsx文件里支持JSX "sourceMap" : true , // 是否生成map文件 "module" : "commonjs" , // 指定生成哪个模块系统代码 "noImplicitAny" : false , // 是否默认禁用 any "removeComments" : true , // 是否移除注释 "types" : [ //指定引入的类型声明文件,默认是自动引入所有声明文件,一旦指定该选项,则会禁用自动引入,改为只引入指定的类型声明文件,如果指定空数组[]则不引用任何文件 "node" , // 引入 node 的类型声明 ], "paths" : { // 指定模块的路径,和baseUrl有关联,和webpack中resolve.alias配置一样 "src" : [ //指定后可以在文件之直接 import * from 'src'; "./src" ], }, "target" : "ESNext" , // 编译的目标是什么版本的 "outDir" : "./dist" , // 输出目录 "declaration" : true , // 是否自动创建类型声明文件 "declarationDir" : "./lib" , // 类型声明文件的输出目录 "allowJs" : true , // 允许编译javascript文件。 "lib" : [ // 编译过程中需要引入的库文件的列表 "es5" , "es2015" , "es2016" , "es2017" , "es2018" , "dom" ] }, // 指定一个匹配列表(属于自动指定该路径下的所有ts相关文件) "include" : [ "src/**/*" ], // 指定一个排除列表(include的反向操作) "exclude" : [ "demo.ts" ], // 指定哪些文件使用该配置(属于手动一个个指定文件) "files" : [ "demo.ts" ] } |
src
目录下添加文件vue-shim.d.ts,告诉 TypeScript
*.vue
后缀的文件可以交给 vue
模块来处理
1 2 3 4 | declare module "*.vue" { import Vue from "vue" ; export default Vue; } |
-
js文件重命名.ts,组件引入加后缀.vue
1).src/main.js修改为main.ts,与webpack入口文件配置相对应;
2).因为Typescript默认只识别*.ts
文件,不识别*.vue
文件,所以import引入组件时需要添加.vue后缀。
-
vue组件ts改造:(从 vue2.5 之后,vue 对 ts 有更好的支持。根据官方文档,vue 结合 typescript ,有两种书写方式,ps:template 和 style 跟以前的写法保持一致,只有 script 的变化)
1).方法一:Vue.extend()。使用基础 Vue 构造器,创建一个“子类”。 这种方式最接近 Vue 的单文件组件的写法,学习成本最低,只要加上 lang=ts
和一些必要的变量类型,然后用Vue.extend()
包裹就好。
// src/components/HelloWorld.vue <script lang= "ts" > import Vue from 'vue' export default Vue.extend({ name: 'HelloWorld' , data () { return { msg: 'Welcome to Your Vue.js App' } } }) </script> |
2).方法二:vue支持ts写法的官方插件:
1.vue-class-component(装饰器@Component)对 Vue 组件进行了一层封装,让 Vue 组件语法在结合了 TypeScript 语法之后更加扁平化;
2.vue-property-decorator(装饰器@Component、@Emit、@Prop、@Watch等)是vue-class-component的扩展,在 vue-class-component 上增强了更多的结合 Vue 特性的装饰器且完全继承与它,开发中只需要引入vue-property-decorator即可,下面详细介绍用法。
三、在vue-cli4+项目中使用typescript
1.vue-cli4框架已经集成typescript环境,初始化项目时可直接勾选配置
2.学习vue-property-decorator库用法,使用vue官方ts插件编写组件
1).@Component装饰器:引入组件
//js写法 <script> import LimitConfigTable from '@/components/config/LimitConfigTable' export default { components: { LimitConfigTable, }, ... } </script> //ts写法 <script lang= 'ts' > import LimitConfigTable from '@/components/config/LimitConfigTable.vue' import {Vue, Component} from 'vue-property-decorator' @Component({ components: { LimitConfigTable, } }) export default class LimitConfig extends Vue{...} </script> |
2).定义data变量:声明类型
//js写法 <script> export default { data(){ return { activeTab: 'PRODUCT' , num: 200, configModalShow: false , param: { pageNum: 1, pageSize: 10, } typeList: [ { value: 'PRODUCT' , label: '产品线product' , }, { value: 'VIEW' , label: '报表view' , } ], } }, ... } </script> //ts写法 <script lang= 'ts' > import {Vue, Component} from 'vue-property-decorator' interface Param { pageNum: number; pageSize: number; [propName: string]: any; //添加索引,当param有其他属性时可以兼容 } interface List { value: string; label: string; } @Component export default class LimitConfig extends Vue{ //我们可以直接按ts定义类变量的写法写就可以 activeTab:string = 'PRODUCT' num:number = 200 configModalShow:boolean = false params: Param = { pageNum: 1, pageSize: 10, } typeList: Array<List> = [ { value: 'PRODUCT' , label: '产品线product' , }, { value: 'VIEW' , label: '报表view' , } ] } </script> |
3).计算属性get、监听属性用@Watch装饰器、method可直接写方法,函数返回类型是可选项
//js写法 <script> export default { computed: { title(){ return this .type != '' ? '编辑配置' : '新建配置' } }, watch: { show: { handler(){ this .form = _.cloneDeep( this .config) }, immediate: true } }, editConfig(index){ this .editItem = this .tableData[index] } ... } </script> //ts写法 <script lang= 'ts' > import {Vue, Component, Watch} from 'vue-property-decorator' //引入@Watch装饰器用于监听属性变化 @Component export default class LimitConfig extends Vue{ //对于Vue中的计算属性,我们只需要将该计算属性名定义为一个函数,并在函数前加上get关键字即可 get title(): string{ return this .type != '' ? '编辑配置' : '新建配置' } //@Watch接受第一个参数为要监听的属性名 第二个属性为可选对象 @Watch( 'show' , {immediate: true }) watchShow(): viod{ this .form = _.cloneDeep( this .config) } editConfig(index: number): void{ this .editItem = this .tableData[index] } } </script> |
4).@Prop装饰器:接收父组件参数.
//js写法 <script> export default { props: { type: { type: String, default : '' }, config: { type: Object, default (){ return {} } }, show: { type: Boolean, required: true , default : false , } }, ... } </script> //ts写法 <script lang= 'ts' > import {Vue, Component, Prop} from 'vue-property-decorator' //引入@Prop装饰器 @Component export default class LimitConfig extends Vue{ //@Prop接受的类型比如Number是JavaScript的类型,之后定义的属性类型则是TypeScript的类型,这里 !和可选参数?是相反的, !告诉TypeScript我这里一定有值. @Prop({type: String, default : '' }) type?: string; @Prop({ default (){ return {}}}) config?: Config; @Prop({ default : false }) show!: boolean; } </script> |
5).@Emit装饰器:事件监听
//js写法 <script> export default { refresh(){ this .$emit( 'refresh' , this .type) } closeModal(){ this .$emit( 'close' ) console.log(123) } ... } </script> //ts写法 <script lang= 'ts' > import {Vue, Component, Prop} from 'vue-property-decorator' //引入@Prop装饰器 @Component export default class LimitConfig extends Vue{ //在@Emit装饰器的函数会在运行之后触发等同于其函数名(驼峰式会转为横杠式写法)的事件, 并将其函数传递给$emit /*@Emit触发事件有两种写法 1.@Emit()不传参数,那么它触发的事件名就是它所修饰的函数名. 2.@Emit(name: string),里面传递一个字符串,该字符串为要触发的事件名.*/ @Emit() //如果函数名相同则可省略 refresh(){ return this .type } @Emit( 'close' ) //写入事件名可触发特定的事件 closeModal(){ console.log(123) } } </script> |
3.vuex-class库支持vuex,装饰器有@State、@Getter、@Action、@Mutation
//js写法 <script> export default { methods: { async getUser() { ... this .role = this .$store.state.erp this .$store.commit( 'setErp' , res.data.erp) this .$store.commit( 'setRole' , res.data.role) ... }, } ... } </script> //ts写法 <script lang= 'ts' > import {Vue, Component} from 'vue-property-decorator' import {State, Mutation} from 'vuex-class' @Component export default class LimitConfig extends Vue{ @State( 'erp' ) stateErp!: string @Mutation( 'setErp' ) MutationErp: any @Mutation( 'setRole' ) MutationRole: any async getUser() { ... this .role = this .stateErp this .MutationErp(res.data.erp) this .MutationRole(res.data.role) ... } } </script> |
4.声明全局方法、变量,新建global.d.ts文件
在main.ts中定义的
Vue.prototype.$get = $get,
当直接使用全局声明的变量时,会提示在该模块中找不到$get属性。需要在**.d.ts文件中全局声明才可以使用
//global.d.ts声明文件 declare module 'vue/types/vue' { // 可以使用 `VueConstructor` 接口 // 来声明全局属性 interface VueConstructor { //全局声明在构造函数 http: any; } } declare module 'vue/types/vue' { interface Vue { //往Vue的实例里面添加属性 $get: any; $post: any; $moment: any; $notify: any; $confirm: any; $JSONEditor: any; } } declare global { const ace: any; } |
4.在shims-vue.d.ts文件中声明第三方插件
在main.ts中引入第三方库时,
import JSONEditor from 'jsoneditor'
Vue.use(VueResource),
会提示无法找到模块“jsoneditor”的声明文件。需要在**.d.ts文件中全局声明才可以使用
declare module '*.vue' { //告诉ts将vue文件交给vue模块处理 import Vue from 'vue' export default Vue } declare module 'vue-privilege-menu' declare module 'vue-resource' declare module 'jquery' declare module 'lodash' declare module 'moment' declare module 'sql-formatter' declare module 'jsoneditor' declare module 'ace-builds' |