项目背景: vue-cli3生成的vue2.x的项目,ide是vscode
1、安装
vue add typescript
? Use class-style component syntax? (Y/n) y
? Use Babel alongside TypeScript for auto-detected polyfills? (Y/n) y
这两项都选择Yes,第一个是因为要使用官方维护的vue-class-component 装饰器来改造项目,第二个babel转义也是需要的。
2、重新看项目
1、之前项目下的.js文件全部变成.ts文件。
2、新增了HelloWolrd.vue,Home.vue ,App.vue文件,可以用来参考vue-class-component写法
3、新增了shims-tsx.d.ts和shims-vue.d.ts 这2个声明文件(**重要,由于没用到jsx语法,因此只关心第二个)
4、新增了tsconfig.json (**重要,ts的配置文件)
3、模块相关问题
1 、之前的引用方式因为偷懒都去掉了文件后缀名,这里需要加上; import xx from xx.vue
2 、import 时路径别名的引用需要在tsconfig.json中添加,如果别名指向了具体文件,这里也需要具体到文件
"paths": {
"@/*": [
"src/*"
],
"@components/*": [
"xxx/xxx/components/*"
]
}
3、import 如果别名指向的是具体的js文件,会报错,没有找到模块xxx的声明文件。
Could not find a declaration file for module '@xxx/vendor'
这时需要修改shims-vue.d.ts声明文件,即可
declare module '@xxx/vender'
(这里说明下,在项目中单独在一个路径维护一个vendor.js文件包括vue,vuex,vie-router等官方库,所有业务统统引用这个vendor,如有版本库更新,只修改这个vendor.js即可)
4、ts相关错误
1、定义对象时记得要声明如, const myObj: {[index: string]:any} = {}
不然在通过myObj[xxx]方式访问属性是报错ts7053
2、window.xxx 报错
用另一个any变量缓存,let win:any = window
在使用(<any>window).xxx访问
3、MyObj.__defineGetter__('xx',function(){}) 报错ts2339
需要使用defineProperty来改造
Object.defineProperty(MyObj,'xx', { get: function(){} } )
**注意 如果是在给构造器添加getter的话,要在其原型链上添加,如下
Object.defineProperty(Number.prototype,'xx',{get: function(){} })
5、vue组件写法
1、store 中的state 需要初始化,不然会报错
2、在vue的原型链上添加或者vue.use(xxx)添加插件时,需要
模块补充,如:
import Vue from "vue"
//在vue组件内疚可以使用this.xxx来访问了
declare module "vue/types/vue" {
interface Vue {
xxx: xxx
}
}
3、tsconfig.json中的typeRoots 配置, 直接指向一个目录,目录下定义全局interface等,使用时不需要import 可以直接用
4、这里有个Keng 。我在x.d.ts中添加了import语句,导致这个d.ts无法被识别,使用时需要import这个d.ts (如何写好一个d.ts文件?)
5、vue-router 导航钩子,需要注册才能使用。(在定义钩子方法时,不能随意添加,只能在router.js中定义的导航组件中添加钩子方法)
Component.registerHooks([
"beforeRouteEnter", //进入路由之前
"beforeRouteLeave", //离开路由之前
"beforeRouteUpdate"
]);
6、this.$refs.xxx.show()
先使用vue-property-decorator 中的Ref修饰器
@Ref() readonly xxx:yyy (xxx是变量名,yyy是引入的.vue文件)
在使用this.xxx.show时会报错:ts2339 property 'show' does not exist on type vue
解决方案:https://stackoverflow.com/questions/57416991/vue-typescript-how-to-avoid-ts-error-when-accessing-child-components-methods
原因:https://github.com/kaorun343/vue-property-decorator/issues/257 .vue文件export的是一个vue 实例,不是我们extends之后的,因此没有我们自定义的property
7、document.getElementById('xxx').style 报错 ts2339 Property 'style' does not exist on type 'Element'
这里因为getElementById/querySelector等方法返回的是Element,Element在W3C中不包含这个,HTMLElement,SVGElement等继承Element 这里在实际使用时,根据实际情况强制类型为HTMLElement。如:`<HTMLDivElement>document.getElementById('xxx')`
6,在原不支持ts的webpack.config.js中对ts的支持
1),RegeneratorRuntime is not defined
npm install --save-dev @babel/plugin-transform-runtime
"plugins": ["@babel/plugin-transform-runtime"] 版本都要7以上
2),TypeError: this.setDynamic is not a function
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
}
都要版本7以上, this.setDynamic 是因为 transform-runtime 是6.x
3),Unexpected token: name «win», expected: punc «;»
是因为uglify-js报错 ,用 terser-webpack-plugin 替换
4),cant not resolve ./poster
import poster from "./poster" (.ts文件)
需要在extension 添加['.ts']
5),Error: Cannot find module '@babel/plugin-runtime'
@babel/runtime isn't a plugin. It's a time package which you should put in your dependencies when using @babel/transform-runime
不是一个plugin ,不能用在pluginconfig中
6),Cannot assign to read only property ‘exports’ of object
import 和 module.exports 不要写在一个文件 或 使用@babel/plugin-transform-runtime
7 , vscode vetur 2307 bug: Cannot find module '@/js/util'
import xxx from @/xxx/xxx 在.vue文件中提示 vetur 2307 找不到module 。 在.ts文件中正常。
tsconfig path 配置了 "@/*": [ "src/*" ]
解决方法: 用vscode 打开tsconfig所在文件夹。让tsconfig.json处于最外层 即可
7) 当我使用 JavaScript 文件时,为什么我会得到 error TS5055: Cannot write file 'xxx.js' because it would overwrite input file 错误?
对于 TypeScript 文件来说,在默认情况下,编译器将在同一目录中生成与 JavaScript 相同文件名的文件。因为 TypeScript 文件与编译后的文件总是拥有不同的后缀,这么做是安全的。然而,如果你设置 allowJs 编译选项为 true 和没有设置任何的编译输出属性(outFile 和 outDir),编译器将会尝试使用相同的规则来编译文件,这将导致发出的 JavaScript 文件与源文件具有相同的文件名。为了避免意外覆盖源文件,编译器将会发出此警告,并跳过编写输出文件。
有多种方法可以解决此问题,但所有这些方法都涉及配置编译器选项,因此建议你在项目根目录中的 tsconfig.json 文件来启用此功能。如果你不想编译 JavaScript 文件,你只需要将 allowJs 选项设置为 false;如果你确实想要包含和编译这些 JavaScript 文件,你应该设置 outDir 或者 outFile 选项,定向到其他位置,这样他们就不会与源文件冲突。如果你仅仅是想包含这些 JavaScript 文件,但是不需要编译,设置 noEmit 选项为 true 可以跳过编译检查。