vue项目引入ts步骤(小结)


Posted in Javascript onOctober 31, 2019

最近考虑到老项目代码的可维护性以及稳定性,决定引入ts做规范检测。因为介绍的东西比较基础,如果介绍的不对,麻烦指正。

1. 简介

TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持。网上关于ts的学习资料很多,这里不做详细介绍。可参考的学习网站:

ts.xcatliu.com/

typescript.bootcss.com/

2. 安装依赖包

cnpm i typescript ts-loader --save-dev

3. 添加tsconfig.json文件

在项目根目录下添加 tsconfig.json 文件。tsconfig.json 文件用来指定ts的编译选项。配置可参考:

https://typescript.bootcss.com/tsconfig-json.html

项目工程 tsconfig.json 文件配置如下:(仅做参考)

{
  "compilerOptions": {
    "baseUrl": ".",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "noEmitOnError": true,
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "allowJs": true,
    "noEmit": false,
    "noImplicitThis": true,
    "esModuleInterop": true,
    "sourceMap": true,
    "moduleResolution": "node"
  },
  "include": [
    "src/**/*", "types"
  ],
  "exclude": [
    "node_modules",
    "build"
  ]
}

4. webpack打包配置修改

webpack.config.js 打包文件修改,新增对.ts文件的打包配置。

4.1 入口文件后缀名由.js修改为.ts

module.exports = {
  entry: {
    app: ['@babel/polyfill', './src/main.ts']
  }
}

4.2 extensions 文件扩展名增加 .ts, .tsx 文件的支持

tsx针对react项目文件的支持,因为我们的工程基于vue开发,支持.ts文件就可以了。

module.exports = {
  resolve: {
    extensions: ['.js', '.vue', '.json', '.css', '.ts']
  }
}

4.3 loader增加对ts文件的支持

使用ts-loader来转换ts文件。

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

5. eslint 添加对ts文件的检测

5.1 安装依赖包

cnpm i @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-typescript eslint-plugin-typescript --save-dev

@typescript-eslint/parser ts文件解析器

@typescript-eslint/eslint-plugin 版本号需要与@typescript-eslint/parser的版本一致,解析器相关的配置选项

eslint-config-typescript 针对ts项目配置的eslint检测规范

5.2 .eslintrc配置文件修改

.eslintrc配置文件修改,支持对ts的文件的校验。经过多次调整,我们工程的 .eslintrc 配置文件如下:

{
  "parserOptions": {
    "parser": "@typescript-eslint/parser",
    "project": "./tsconfig.json",
    "extraFileExtensions": [".vue"],
    "ecmaVersion": 2017,
    "sourceType": "module",
    "ecmaFeatures": {
      "modules": true
    }
  },
  "env": {
   "jest": true,
   "browser": true
  },
  "settings": {
   "import/resolver": {
    "node": {
     "extensions": [".js", ".jsx", ".ts", ".tsx", ".eslintrc"]
    },
    "webpack": {
     "config": {
      "resolve": {
       "alias": {
        "src": "src"
       }
      }
     }
    }
   }
  },
  "plugins": [
    "vue",
    "babel",
    "@typescript-eslint"
  ],
  "extends": [
    "eslint:recommended",
    "plugin:vue/base",
    "typescript",
    "standard"
  ],
  "rules": {
    "func-names": 0,
    "one-var": [1, "never"],
    "prefer-const": 1,
    "no-unused-expressions": 1,
    "new-cap": 2,
    "prefer-arrow-callback": 2,
    "arrow-body-style": 0,
    "max-len": [
      1,
      {
      "code": 200,
      "ignoreStrings": true,
      "ignoreUrls": true,
      "ignoreRegExpLiterals": true
      }
    ],
    "consistent-return": "off",
    "default-case": 2,
    "prefer-rest-params": 2,
    "no-script-url": 0,
    "no-console": [
      2,
      {
      "allow": ["info", "error", "warn", "log"]
      }
    ],
    "no-duplicate-imports": 2,
    "newline-per-chained-call": 2,
    "no-underscore-dangle": 2,
    "eol-last": 2,
    "no-useless-rename": 2,
    "class-methods-use-this": 0,
    "prefer-destructuring": 0,
    "no-unused-vars": 0,
    "@typescript-eslint/no-unused-vars": 1,
    "no-plusplus": 0,
    "import/prefer-default-export": 0,
    "import/no-dynamic-require": 2,
    "@typescript-eslint/no-var-requires": 2,
    "no-use-before-define": [
      "error",
      {
      "functions": false
      }
    ],
    "@typescript-eslint/no-use-before-define": 0,
    "@typescript-eslint/explicit-function-return-type": 0,
    "@typescript-eslint/interface-name-prefix": 0,
    "no-invalid-this": 0,
    "babel/no-invalid-this": 2,
    "no-await-in-loop": "off",
    "array-callback-return": "off",
    "no-restricted-syntax": "off",
    "@typescript-eslint/no-explicit-any": 0,
    "import/no-extraneous-dependencies": 0,
    "import/no-unresolved": 0,
    "@typescript-eslint/explicit-member-accessibility": 0,
    "@typescript-eslint/no-object-literal-type-assertion": 0,
    "no-param-reassign": [
      2,
      {
      "props": false
      }
    ],
    "generator-star-spacing": "off",
    "indent": [2, 4, {
      "SwitchCase": 1
    }],
    "eqeqeq": 0,
    "no-else-return": 2,
    "arrow-parens": 0,
    "space-before-function-paren": ["error", "never"],
    "comma-dangle": [2, "never"],
    "semi": [2, "always"]
  }
 }

注意"extends": ["plugin:vue/base"], 只能选择vue/base,不能用vue/recommend。不然会有规则冲突。

6. 项目文件转换

项目配置好后,开始对老代码进行改造,来支持ts的语法检测。

6.1 增加ts声明文件目录

项目中总会依赖一些资源包,或是自己开发的一些组件,这些文件需要补充声明文件,声明文件就是将多个声明语句放在一起,这些声明文件可统一放到一个目录里。这个目录需要包含在 tsconfig.json 文件的include里。

ms工程在根目录下新建 types 目录,目前包含 vue.d.ts, request.d.ts, dialog.d.ts, base.d.ts 等文件。

6.2 全局vue.d.ts声明文件

需要在ts环境下识别vue文件,需要添加 vue.d.ts 全局声明文件,例子如下:

import VueRouter, { Route } from 'vue-router';
import RequestAxios from './request';

declare module '*.vue' {
  import Vue from 'vue';
  export default Vue;
}
declare module 'vue/types/vue' {
  interface Vue {
    $router: VueRouter;
    $route: Route;
    $request: RequestAxios;
    ....
  }
}

6.2 vue文件的改造

vue文件的改造,只改造js部分,代码大致修改如下:

import { Vue, Component, Prop, Watch } from 'vue-property-decorator';

@Component({
  components: {
    ....
  }
})
export default class MyComponent extends Vue {
  // prop
  @Prop({ default: () => {} }) readonly pageInfo !: any

  // data
  private showAnimation : boolean = true;

  // watch
  @Watch('showModuleIndex')
  onShowModuleIndexChanged(newValue: any) {
    this.$emit('input', newValue);
  }

  // computed
  get list() {
    const { page, cityList } = this;
    return page.cityList.split(',').map(
      cityId => cityList.find(c => String(c.id) === cityId)
    );
  }

  // mounted
  private mounted() :void {
    this.initEditor();
  }

  // methods
  private initEditor() :void {
    ....
  }
}
</script>

6.3 js文件的改造

将文件后缀名更改为.ts,然后加上类型就可以了。

7. 踩坑总结

大部分都是eslint校验时的报错,按照提示修复就可以了。

"vue/html-indent": [2, 4] eslint这条规则去掉

"plugin:vue/base"与"plugin:vue/recommend"的区别

...

8. 总结

项目改造过程中,大部分时间都是在查配置兼容问题,配置这块解决了,改造起来速度还是挺快的。虽然前期会有一些改造成本,但是长远来看,还是有意义的。毕竟很多代码类型上的问题在开发阶段就可以暴露,不用等到运行时才发现了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript中的array数组使用技巧
Jan 31 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
Jan 23 Javascript
查找iframe里元素的方法可传参
Sep 11 Javascript
javascript从image转换为base64位编码的String
Jul 29 Javascript
javascript高级编程之函数表达式 递归和闭包函数
Nov 29 Javascript
利用node.js实现自动生成前端项目组件的方法详解
Jul 12 Javascript
Vue中在新窗口打开页面及Vue-router的使用
Jun 13 Javascript
Angular ui-roter 和AngularJS 通过 ocLazyLoad 实现动态(懒)加载模块和依赖
Nov 25 Javascript
Vuex的初探与实战小结
Nov 26 Javascript
JS立即执行的匿名函数用法分析
Nov 04 Javascript
微信小程序实现简单文字跑马灯
May 26 Javascript
JavaScript实现10秒后再次获取验证码
Dec 02 Javascript
微信小程序canvas分享海报功能
Oct 31 #Javascript
解决vue初始化项目时,一直卡在Project description上的问题
Oct 31 #Javascript
vue项目初始化到登录login页面的示例
Oct 31 #Javascript
vue3 源码解读之 time slicing的使用方法
Oct 31 #Javascript
vue data恢复初始化数据的实现方法
Oct 31 #Javascript
vue和iview实现Scroll 数据无限滚动功能
Oct 31 #Javascript
vue 使用鼠标滚动加载数据的例子
Oct 31 #Javascript
You might like
自动分页的不完整解决方案
2007/01/12 PHP
PHP使用array_merge重新排列数组下标的方法
2015/07/22 PHP
ThinkPHP中调用PHPExcel的实现代码
2017/04/08 PHP
visual studio code 调试php方法(图文详解)
2017/09/15 PHP
PHP+Session防止表单重复提交的解决方法
2018/04/09 PHP
Javascript 函数parseInt()转换时出现bug问题
2014/05/20 Javascript
JavaScript function函数种类详解
2016/02/22 Javascript
js实现统计字符串中特定字符出现个数的方法
2016/08/02 Javascript
jquery实现ajax提交表单信息的简单方法(推荐)
2016/08/24 Javascript
微信小程序 Video API实例详解
2016/10/02 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
2016/11/06 Javascript
jQuery中ajax错误调试分析
2016/12/01 Javascript
js实现短信发送倒计时功能(正则验证)
2017/02/10 Javascript
Vue.js原理分析之observer模块详解
2017/02/17 Javascript
Vue源码解读之Component组件注册的实现
2018/08/24 Javascript
基于Vue实现可以拖拽的树形表格实例详解
2018/10/18 Javascript
socket io与vue-cli的结合使用的示例代码
2018/11/01 Javascript
使用layui+ajax实现简单的菜单权限管理及排序的方法
2019/09/10 Javascript
[03:58]兄弟们,回来开黑了!DOTA2昔日战友招募宣传视频
2016/07/17 DOTA
python使用fileinput模块实现逐行读取文件的方法
2015/04/29 Python
简单谈谈Python中的几种常见的数据类型
2017/02/10 Python
Python多层装饰器用法实例分析
2018/02/09 Python
python操作mysql代码总结
2018/06/01 Python
[机器视觉]使用python自动识别验证码详解
2019/05/16 Python
python输出电脑上所有的串口名的方法
2019/07/02 Python
python的命名规则知识点总结
2019/10/04 Python
Python实现电视里的5毛特效实例代码详解
2020/05/15 Python
python利用 keyboard 库记录键盘事件
2020/10/16 Python
详解移动端HTML5音频与视频问题及解决方案
2018/08/22 HTML / CSS
澳大利亚最大的百货公司:Myer
2018/12/21 全球购物
澳大利亚在线划船、露营和钓鱼商店:BCF Australia
2020/03/22 全球购物
幼儿园门卫岗位职责
2014/02/14 职场文书
十佳党员事迹材料
2014/08/28 职场文书
干部考察材料范文
2014/12/24 职场文书
新教师个人总结
2015/02/06 职场文书
优秀党员主要事迹材料
2015/11/04 职场文书