vue2.6项目配置typescript+vue-class-component/vue-property-decorator

811 阅读2分钟

增加typescript,ts-loader,@babel/plugin-proposal-class-properties,@babel/plugin-proposal-decorators

npm i -D ts-loader typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators

@babel/plugin-proposal-class-properties 是为了支持在class中用类属性的写法: image.png @babel/plugin-proposal-decorators是为了支持在class中用装饰器语法: image.png 并在babel.config.js中增加配置: image.png 对tsconfig.json做修改: image.png 其中需要关注的是

  1. "module": "es2020" 因为我使用了动态import,如果module是"es6"或者更低则不识别动态import。
  2. "experimentalDecorators": true 支持装饰器语法。
  3. "emitDecoratorMetadata": true 配合reflect-metadata包。

在vue.config.js中增加ts-loader配置。起初我在chainWebpack中配置: image.png

但是编译时报错不识别装饰器符号'@', image.png 在排查了vue-loader、vue-template-compiler,@babel/plugin-proposal-decorators,@babel/plugin-proposal-class-properties,ts-loader配置之后,把ts-loader的配置放到configureWebpack中后,这个报错消失了:

image.png

在这过程中了解到vue-loader从15版本开始借助vue-template-compiler把SFC文件的各个语法块解析成descriptorimage.png 然后selectBlock方法中使用webpack中配置的module的loader去编译各个语法块: image.png

因此上面报错不识别'@'符号,而且提示需要另外的loader去处理vue-loader的结果,应该就是ts-loader没配置好。

文件后缀类型中增加ts image.png

增加vue-class-component,vue-property-decorator

npm i vue-class-component vue-property-decorator reflect-metadata

然后就是把.js文件改成.ts.vue中的<script>变成<script lang="ts">vue-class-component + vue-property-decorator的配置方式参看各自文档即可。

为了不让在引用.vue文件时报错

image.png

创建一个.d.ts文件对.vue后缀的文件做一个类型声明,并在tsconfig.json的include中加上该文件 image.png

我增加的vue-shim.d.ts文件如下:

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

declare module 'vue/types/vue' {
  export interface Vue {
    /**
     * 
      自定义的比如 Vue.prototype.$api = myApi 这样的全局属性,要在vue组件内用 this.$api 时类型
      检验不报错,就需要在这里加声明,比如:
      $api: any
     */
  }
}

改用@typescript-eslint/parser

npm i @typescript-eslint/eslint-plugin @typescript-eslint/parser

增加.eslintrc.js文件:详细配置参考@typescript-eslint/parser文档

module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  plugins: [
    '@typescript-eslint',
  ],
  env: {
    browser: true
  },
  extends: [
    "plugin:vue/essential",
    "eslint:recommended",
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
  ],
  "parserOptions": {
    tsconfigRootDir: __dirname,
    project: ['./tsconfig.json'],
    extraFileExtensions: ['.vue'],
  },
  "rules": {
    "vue/no-unused-components": "warn"
  }
};