本文共 6219 字,大约阅读时间需要 20 分钟。
摘要:TypeScript是王道。
经授权转载,版权归原作者所有。
javascript由于自身的弱类型,使用起来非常灵活。
这也就为大型项目、多人协作开发埋下了很多隐患。如果是自己的私有业务倒无所谓,主要是对外接口和公共方法,对接起来非常头疼。主要表现在几方面:
这就非常不利于工程标准化。于是我们决定引入typescript进行代码层面的强校验。
原有vue项目接入ts主要包含下面几大步骤:
ok,我们开始
这块有个非常重要的点需要注意:
就是要根据你本地的环境,去升级对应版本的typescript
这块是很多初次使用的同学都会遇到的问题。
因为只是看到了官网的教程,一步一步安装完发现各种报错。主要问题就是webpack版本不匹配,或者其他一些npm包版本不匹配
我本地环境是webpack3,所以直接安装最新版本的typescript,控制台会报错webpack版本过低的问题。
所以你要不把自己的webpack升级到webapck4.要不就采用与之相匹配的typescript版本。
我选择的是后者,因为直接给自己的项目升级到webapck4,会花费更长的时间。我们用的脚手架是公司内部统一的。里面集成了很多底层通用的基础服务。冒然升级webpack4会带来更大的麻烦,更何况项目时间比较紧迫,你懂得。
下面是我安装的包和对应的版本:
base: { entry: { ... app: resolve('src/main.ts') // 把main.js改为main.ts }...resolve: { ... extensions: ['vue', '.js', '.ts']}module: { rules: [ ..., { // 加入对文件的ts识别 test: /\.ts$/, exclude: /node_modules/, enforce: 'pre', loader: 'tslint-loader' }, { test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, options: { appendTsSuffixTo: [/\.vue$/], } } ]}
注意: main.js改成main.ts后,还要做一些改造,这个比较简单,按照tslint的错误提示改就可以了
{ "extends": "tslint-config-standard", "globals": { "require": true }}
{ "compilerOptions": { // 编译目标平台 "target": "es5", // 输出目录 "outDir": "./dist/", // 添加需要的解析的语法,否则TS会检测出错。 "lib": ["es2015", "es2016", "dom"], // 模块的解析 "moduleResolution": "node", // 指定生成哪个模块系统代码 "module": "esnext", // 在表达式和声明上有隐含的any类型时报错 "noImplicitAny": false, // 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件 "sourceMap": true, // 允许编译javascript文件 "allowJs": true, // 指定基础目录 "baseUrl": "./", // 启用装饰器 "experimentalDecorators": true, // 移除注释 "removeComments": true, "pretty": true, // 是相对于"baseUrl"进行解析 "paths": { "vue": ["node_modules/vue/types"], "@/*": ["src/*"] } }, "include": [ "src/**/*" ], "exclude": [ "node_modules" ]}
我们在这里主要是让ts识别.vue文件、window对象和一些module
具体declare的使用方式请看
/** * 告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理 * 而在代码中导入 *.vue 文件的时候,需要写上 .vue 后缀。 * 原因还是因为 TypeScript 默认只识别 *.ts 文件,不识别 *.vue 文件 */declare module "*.vue" { import Vue from 'vue' export default Vue}/** * 告诉 TypeScript window是个全局对象,直接可用,这样就不会在window.xx = 123时报错 */declare var window: any/** * 引入部分第三方库/自己编写的模块的时候需要额外声明文件 * 引入的时候,需要使用类似 import VueLazyLaod from 'vue-lazyload' 的写法 */declare module 'vue-lazyload'declare module '@zz/perf/vue'declare module 'raven-js'declare module 'raven-js/plugins/vue'
将src/main.js改为main.ts
这个部分是最麻烦的,主要有几大块
如果你的基础库引用了大量的npm包,那么恭喜你,这部分你的改造成本会低很多。
如果你的lib库有相当一部分都是自己手写的,那么,我也得恭喜你。。。
我们自己的lib库里,有大量的自己维护的js文件。那么如果你要进行ts改造的话,通通都要改。
举个例子: lib/url.js中的getParam (算法并不高级,就是易读、兼容性好)
export default class URL{ /** * @memberOf URL * @summary 获取当前页面连接中指定参数 * @type {function} * @param {string} param1 - 如果param2为undefined,param1是指从当前页面url中获取指定参数的key, 如果param2不为空,param1为指定的url * @param {string} param2 - 可选参数,如果param2存在,则从指定的param1连接中获取对应参数的key * @return {string|null} */ static getParam (param1, param2) { let url = '' let param = null; // 如果只有一个参数,默认从当前页面链接获取参数 if (typeof param2 === 'undefined') { url = window && window.location.href || '' param = param1 // 从指定url中获取参数 } else { url = param1 param = param2 } // 排除hash的影响 url = url.split('#')[0] if (url.indexOf('?') > -1) { url = url.split('?')[1] } const reg = new RegExp('(^|&)' + param + '=([^&]*)[&#$]*', 'i') const rstArr = url.match(reg) if (rstArr !== null) { return decodeURIComponent(rstArr[2]) } return null } ...}
改造后的文件为:lib/url.ts
export default class URL { /** * @memberOf URL * @summary 获取url中指定参数 * @type {function} * @param {string} param1 - 如果param2为undefined,param1是指从当前页面url中获取指定参数的key, 如果param2不为空,param1为指定的url * @param {string} param2 - 可选参数,如果param2存在,则从指定的param1连接中获取对应参数的key * @return {string|null} */ static getParam (param1: string, param2?: string): string { let url: string = '' let param = null // 如果只有一个参数,默认从当前页面链接获取参数 if (typeof param2 === 'undefined') { url = window && window.location.href || '' param = param1 // 从指定url中获取参数 } else { url = param1 param = param2 } url = url.split('#')[0] if (url.indexOf('?') > -1) { url = url.split('?')[1] } const reg = new RegExp('(^|&)' + param + '=([^&]*)[&#$]*', 'i') const rstArr = url.match(reg) if (rstArr !== null) { return decodeURIComponent(rstArr[2]) } return null } ...}
对于一个方法多种调用方式,如果你想完全改成typescript推荐的方式,你可以用到。
我没有用是因为我不希望改变原有页面的使用方式。
注:对于一个大型项目来讲,我们并不建议上来就对全部的文件进行ts改造。
我们更建议采用渐进式改造方案,在不影响原有页面的情况下,逐一改造。具体方案后面会介绍
src/components/helper/newUser/index.vue
...
改造后
...
myComponent.vue改造前略,这里只展示改造后的组件
{ {title}}{ {name}}
这里需要注意的是:
现在说下前面提到的改造方案:
这里其实主要涉及.vue文件和lib库的改造,vue文件没啥可说的,一个个改就可以了。主要说lib里面的文件,这里我建议:
ok以上就是我们改造的全部过程。 有什么问题可以指正,大家互相学习。
专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了9亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!
转载于:https://blog.51cto.com/13957060/2324177