在Vue2.5中使用typeScript

Posted by Yinode on Wednesday, January 10, 2018

TOC

本文的环境依旧是由Vue-cli工具初始化的。

安装 


npm install typescript ts-loader --save-dev

配置

首先在webpack.base.config.js中设置一下基本的Loader规则


// 还有别忘了在resolve的扩展名中增加.ts的后缀

  {
    test: /\.tsx?$/,
    loader: 'ts-loader',
    exclude: /node_modules/,
    options: {
      appendTsSuffixTo: [/\.vue$/]
    }
  }

接下来我们需要scr中创建一个名为 vue-shims.d.ts的类型声明文件来让ts能够正确识别.vue文件 ,内容如下

src/types/vue-shims.d.ts


declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

之后如果你引入了其他一些库,发现TS提示这个模块没有类型声明文件的话,并且 npm i @types/moduleName也下载不到。你可以在这个文件中增加声明 比如我的模块叫vueBar,就加入declare module 'vuebar

  • 要在根目录创建一个tsconfig.json的配置文件,我们之后再提

但是到这里能够正常使用TS是远远不够的,我将按照具体vue全家桶的组成来讲述一下流程

1 配置单页面文件和基本组件

首先必须把script加上ts的语言标记

然后安装一个类扩展的库,来帮助TS对Vue的组件系统有正确的推断

cnpm i vue-class-component --save-dev

之后在我们的.vue文件中使用他,他的使用大致上如下。这里是@本质上是一个TS的装饰器。


<template>

</template>

<script lang='ts'>
import Vue from 'vue'
import Component from 'vue-class-component'
@Component({
  name:'App'
})

export default class App extends Vue{
  
}
</script>

<style>

</style>

当然你可能还会需要使用诸如props,watch等Vue内置的功能,还需要安装一个额外的扩展 vue-property-decorator

2 Vue-router

基本不需要什么特别的配置,只要把js.改成ts即可。不会出现特别的类型错误。

3 Vuex

Vuex是比较麻烦的点,首先是注册


import Vue from 'vue'

// 需要使用 Vuex 的 interface 
import Vuex, { ActionTree, MutationTree } from 'vuex'

Vue.use(Vuex)

interface State  {
  name: String;
}

const state: State = {
  name: '33333'
}

const actions: ActionTree<State, any> = {
  changName (
    { commit },
    name: String
  ): void {
    commit('CHANGE_NAME', name)
  }
}

const mutations: MutationTree<State> = {
  'CHANGE_NAME' (
    state: State,
    name: String
  ): void {
    state.name = name
  }
}

export default new Vuex.Store({
  state,
  actions,
  mutations
})

之后在实例中使用,需要安装一个库 vuex-class


<script lang='ts'>
import Vue from 'vue'
import Component from 'vue-class-component'
import {
  State,
  Mutation
} from 'vuex-class'

@Component({
  name:'TS'
})
export default class Hello extends Vue {
  @State(state=>state.name) myName:string
  @Mutation('CHANGE_NAME') M_ChangeName:any
  
  msg: String = this.myName

  changeName(){
    this.M_ChangeName('nihao')
  }
}
</script>

如果你出现了一些提示错误,最好去查阅一下,一般都是配置文件出了问题。最后加上我自己的配置文件


{
  "compilerOptions": {
    // 与 Vue 的浏览器支持保持一致
    "target": "es5",
    // 这可以对 `this` 上的数据属性进行更严格的推断
    "strict": true,
    // 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake:
    "module": "es2015",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "noImplicitAny": true,
    "lib":["es2015","dom"]
  }
}

其实我觉得TS某种意义也算是双刃剑,它可以帮你提前检查出一些代码之中的bug,其中最重要的也就是类型错误,比如说你调用某个函数的时候,函数的标准输入是数字,而你却传入一个字符串,这时候TS就能帮你提前预告这个错误。

但是某些情况下强类型可能也会给你带来一些不遍,特别是在Vue中使用可能还是会有一些晦涩吧,比如说一些运行时的情况导致你明明不想也不需要进行检查,但TS就是固执的给你报错。特别是Vue这种强DOM的框架,很多时候会依赖ref进行调用子组件方法,或者操作DOM。那你可能就需要写强制类型断言了。

另外就是VSCode的支持也许没那么美好,在极少数情况下会发生没有刷新我在类型声明文件中的声明而导致检查不出来,显示错误。需要重启编辑器。

抛开这些问题不谈,我对于TS居然还满喜欢的,一开始我知道他的时候还真是蛮抗拒,但慢慢的也喜欢上了他给我带来的便利。

最后,也希望vue对于TS的支持能够越来越好吧