typescript进阶—vue项目实战

ts基础类型:查阅最全面的官方API文档(https://www.tslang.cn/docs/handbook/basic-types.html

re-ts git地址:https://git.jd.com/yuwenbinjie/re-ts

一、项目中接入typescript的好处

  1. javascript本身属于弱类型,使用起来比较灵活,所以当前端项目多人协作开发时对接成本较高;
  2. js中参数类型没有校验,也没有规范的接口文档,需要从业务代码上下文中读取

所以在项目中引入ts可以增加代码可读性,减少对接成本,利于工程标准化。

 

二、在vue-cli2.x项目中接入typescript,不推荐在原有项目上修改

  1. 安装ts环境依赖:npm i typescript ts-loader@^3.5.0 --save-dev;
     
  2. 配置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$/]

          }

        }

      ]

    }

  3. 在项目根目录下建立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"

      ]

    }

  4. src目录下添加文件vue-shim.d.ts,告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理

     

    1

    2

    3

    4

    declare module "*.vue" {

      import Vue from "vue";

      export default Vue;

    }

  5. js文件重命名.ts,组件引入加后缀.vue
    1).src/main.js修改为main.ts,与webpack入口文件配置相对应;
    2).因为Typescript默认只识别*.ts文件,不识别*.vue文件,所以import引入组件时需要添加.vue后缀。
     

  6. 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,

            defaultfalse,

        }

    },

    ...

}

</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({defaultfalse}) 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'

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值