vue项目配置使用flow类型检查的步骤


Posted in Javascript onMarch 18, 2020

你是否经常在debug那些简单可避免的bug?可能你给函数传参的时候搞错了参数的顺序,或者本来应该传个Number类型的参数,你传了一个String类型?JavaScript的弱类型是这一类bug的罪魁祸首,静态类型语言中不存在此类bug。Flow就是JavaScript的静态类型检查工具,该库的目标在于检查JavaScript中的类型错误,开发者通常不需要修改代码即可使用,故使用成本很低。同时,它也提供额外语法支持,使得开发者能更大程度地发挥Flow的作用。

一、flow的安装

flow可以直接通过npm或者yarn安装。

这里以npm为例:npm install --save-dev flow-bin

安装完成后在package.json中加入下面的脚本

"scripts": {
  "flow":"flow check"
 }

同时还要安装babel编译器,将flow的类型检查代码从代码中剥离,转变成正常的js代码

npm install --save-dev babel-cli babel-preset-flow

在babel配置文件.babelrc中加入

{
 "presets": ["flow"]
}

二、flow使用

1、配置flow

npm run flow init生成flow配置文件.flowconfig

[ignore]
.*/node_modules/.*
.*/test/.*
.*/build/.*
.*/config/.*
[include]

[libs]

[options]
module.file_ext=.vue 
module.file_ext=.js

[ignore]:Flow 默认检查项目目录下所有文件,但是有很多文件必定是我们不想检查的,就像 node_modules、build 等目录下的文件,所以我们需要在将这些目录写在 ignore 配置下。

[include]:所谓的项目目录其实是 .flowconfig 目录,并不是真正的项目目录,如果我们在这个项目中的某个目录下创建一个 .flowconfig,那么 .flowconfig 所在的目录也会变为一个 Flow 项目。那么,如果我们想对当前 Flow 项目以外的文件或者目录进行检查,需要把它们写在 include 配置项中。

[libs]:在项目中,我们可能会用到很多自定义的类型,比如说要记录对象的结构,它可能在每个文件中都会被运用到,我们将其抽取为全局的类型或数据结构,在任何文件都可以使用。为了管理方便,我们将全局类型都定义在一个或多个单纯的目录中统一管理。这里存放的有可能是一个定义好的数据结构,存放的也有可能是根据项目中某个类对应的数据类型。我们将这些文件或目录写在 libs 配置项中,这个配置对于我们使用 Flow 来说很重要。

[options]:这里填写对 Flow 项目的一些配置,配置项以key=value的形式,每行写一个。所有的配置见官方文档

[lints]:官网中没有提到 lints 相关的配置

2、新建一个文件index.js

// @flow 
let a:number = '3';
// @flow或者 /* @flow */,告诉flow检查这个文件

如果不愿意那么麻烦,想检查全部文件,那么可以修改配置文件.flowconfig,在[options]配置项中添加 all=ture。

[ignore]
[include]
[libs]
[options]
all=true
[lints]

[libs] 配置项中的文件不需要添加// @flow,它们都将被检查。

注:在vue单文件组件使用flow需要额外配置:

(1)在.flowconfig文件的[options]中配置.vue文件扩展名,module.file_ext=.vue

(2)在.vue文件中需注释掉template script styled标签

输入npm run flow 执行类型检查。

注:完成设置之后,在终端输入以下命令可以在你的项目根目录以及任何子目录文件夹下进行专门的类型检查:npm run flow check,但是,这并不是最高效的使用方式,因为每次Flow都会重新检查整个项目的所有文件。开发过程中,推荐启动Flow服务:Flow服务的工作方式是增量检查,也就是说它只检查变化的部分。在终端输入以下命令来启动Flow服务:npm run flow,首次运行该命令时,服务启动并且显示最初类型检查结果。这保证了Flow更高效的增量式工作流。然后接下来每次想要知道检测结果,只要输入flow命令即可。开发结束之后,输入npm run flow stop停止服务。

Flow的类型检查是可选的,并不需要一次性检查所有代码。你可以选择你想要检查的文件,只要在对应的JavaScript文件最前面加上带有@flow标识的注释即可:/*@flow*/,当你想在已有项目中加入Flow的时候,该特性特别有帮助。因为你可以一一选择并检测你要的文件,然后修正错误。

三、类型推断

通常,类型检查分为以下两种方式:

通过注释:事先注释好我们期待的类型,Flow就会基于这些注释来评估

通过代码推断:通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型

第一种方式,我们需要额外编写只在开发阶段起作用的代码,最后在代码编译打包的阶段被剔除。显然,这种额外添加类型注释的方式增加了工作量。

第二种方式,不需要任何代码修改即可进行类型检查,最小化开发者的工作量。它不会强制你改变开发习惯,因为它会自动推断出变量的类型。这就是所谓的类型推断,Flow最重要的特性之一。

我们来通过一个例子来说明这个特性:

/*@flow*/
function foo(x) {
 return x.split(' ');
}

foo(34);

当你在终端运行npm run flow命令的时候,上述代码会报错,因为函数foo()的期待参数是字符串,而我们输入了数字。错误信息类似如下:

index.js:4
  4:   return x.split(' ');
                ^^^^^ property `split`. Property not found in
  4:   return x.split(' ');
              ^ Number

上述信息清楚地指出了出错位置和错误原因。我们只要将参数变成字符串,即可修正错误。该例想说明的是,因为split()方法只适用于string类型的变量,所以x应该是string,这就是类型推断。

四、空类型

Flow处理null的方式与其他类型库不同。它不会忽略null,这样可以防止了因给变量传了null而导致程序崩溃的错误。

/*@flow*/
function stringLength (str) {
 return str.length;
}
var length = stringLength(null);
Flow会报错。为了防止出错,我们需要单独处理null。


/*@flow*/
function stringLength (str) {
 if (str !== null) {
  return str.length;
 }
 return 0;
}
var length = stringLength(null);

代码中我们引入对null的检查,确保代码能在任何情况下都正常且正确运行。上述代码可以通过Flow的类型检查。

五、类型注释

如上所述,类型推断是Flow最有用的特性之一,不需要编写类型注释就能获取有用的反馈。但在某些特定的场景下,添加类型注释可以提供更好更明确的检查依据。考虑以下代码:

/*@flow*/
function foo(x, y){
 return x + y;
}
foo('Hello', 42);

Flow检查上述代码时检查不出任何错误,因为+即可以用在字符串上,也可以用在数字上,我们并没有明确指出add()的参数必须为数字。

在这种情况下,我们可以借助类型注释来指明期望的类型。类型注释是以冒号:开头,可以在函数参数,返回值,变量声明中使用。如果我们在上段代码中添加类型注释,就会变成如下:

/*@flow*/
function foo(x : number, y : number) : number {
 return x + y;
}
foo('Hello', 42);

现在Flow就能检查出错误,因为函数参数的期待类型为数字,而我们提供了字符串。Flow报错信息类似如下:

index.js:7
  7: foo('Hello', 42);
         ^^^^^^^ string. This type is incompatible with the expected param type of
  3: function foo(x : number, y : number) : number{
                      ^^^^^^ number

如果传入的参数是数字,就不会有错误。类型注释在大型复杂的JavaScript文件中也很有用,它能保证代码按照预期进行。

六、Flow能支持的其他更多类型注释。

其实说到底就是类似java那种强语言类型的写法,给每个变量声明是什么类型,给每个函数声明返回值类型,给每个数组元素声明类型等,就是仿造java的写法,哈哈,java传值不对时就会给你报错一样的道理

1、函数

/*@flow*/
function add(x : number, y : number) : number {
 return x + y;
}
add(3, 4);

上述代码展示了变量类型注释以及函数类型注释。函数add()的参数,以及函数的返回值,期待类型为数字。如果传入其他类型参数,Flow就会检测到错误。

2、数组

var foo : Array<number> = [1,2,3];

数组类型注释的格式是Array<T>,T表示数组中每项的数据类型。在上述代码中,foo是每项均为数字的数组。

3、类

下面展示了类和对象的类型注释模型。唯一需要注意的是,可以在两个类型之间使用或逻辑,用|来间隔。变量bar1添加了必须为Bar类的类型注释。

class Bar{
 x:string;      // x should be string    
 y:string | number; // y can be either a string or a number
 constructor(x,y){
  this.x=x;
  this.y=y;
 }
}

var bar1 : Bar = new Bar("hello",4);

4、对象字面量

对象的类型注释类似于类,指定对象属性的类型。

var obj : {a : string, b : number, c: Array<string>, d : Bar} = {
 a : "hello",
 b : 42,
 c : ["hello", "world"],
 d : new Bar("hello",3)
}

5、Null

若想任意类型,T可以为null或者undefined,只需类似如下写成 ?T 的格式即可。

/*@flow*/
var foo : ?string = null;

此时,foo可以为字符串,也可以为null。

目前我们只对Flow的类型注释做了很浅的探索。一旦你习惯了使用这些基本类型,建议在Flow官网上的类型文档深入了解所有的类型。

七、库定义

我们经常需要引入第三方库,Flow检查时就会抛出错误。但这并不是我们期待的错误。

庆幸的是,我们不需要修改库源码去防止这些报错。我们只需创建一个库定义(libdef)。libdef是包含第三方库声明的JS文件简称。观察下面的例子:

/* @flow */
var users = [
 { name: 'John', designation: 'developer' },
 { name: 'Doe', designation: 'designer' }
];

function getDeveloper() {
 return _.findWhere(users, {designation: 'developer'});
}

Flow会检查出以下错误:

interfaces/app.js:9
  9:   return _.findWhere(users, {designation: 'developer'});
              ^ identifier `_`. Could not resolve name

由于Flow并不认识_,所以会报错。要解决这个问题,我们需要引入Underscore的库定义

1、使用flow-typed

flow-typed仓库包含了众多流行的第三方库的libdef。只需在项目根目录下创建一个名为flow-typed的文件夹,并且下载相关的定义文件即可。为了进一步简化,可以用npm的命令行方式一键获取和安装libdef文件:npm install -g flow-typed

安装成功之后, 运行flow-typed install来检查package.json文件,并且下载所有项目中用到的第三方库的libdef。

2、自定义libdef

如果你用的库并不在flow-typed仓库,你可以创建你自己的libdef。本文不会细谈自定义libdef,因为很少会有人遇到,感兴趣可以查看此文档。

八、剔除类型注释

由于额外添加的类型注释不是正确的JavaScript语法,打包编译的时候需要在源码中剔除。可以通过flow-remove-types来剔除,或者如果你已经用Babel来转译JS,你可以使用Babel preset来移除。我们只讨论第一种方法。

首先需要安装flow-remove-types作为项目依赖库:npm install --save-dev flow-remove-types

然后在package.json文件中添加另一个script入口:

"scripts": {
 "flow": "flow",
 "build": "flow-remove-types src/ -D dest/",
}

上述命令将剔除src文件夹下的所有类型注释,在dist文件夹中保存编译后的版本。编译后的文件就是普通的能运行于浏览器的JavaScript文件。

到此这篇关于vue项目配置使用flow类型检查的步骤的文章就介绍到这了,更多相关vue flow类型检查内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery 解析xml文件
Aug 09 Javascript
Javascript面向对象编程(三) 非构造函数的继承
Aug 28 Javascript
jQuery实现密保互斥问题解决方案
Aug 16 Javascript
js中document.write使用过程中的一点疑问解答
Mar 20 Javascript
jQuery给多个不同元素添加class样式的方法
Mar 26 Javascript
微信小程序 获取设备信息 API实例详解
Oct 02 Javascript
springmvc接收jquery提交的数组数据代码分享
Oct 28 jQuery
使用Vue开发一个实时性时间转换指令
Jan 17 Javascript
vue cli2.0单页面title修改方法
Jun 07 Javascript
Layer.js实现表格溢出内容省略号显示,悬停显示全部的方法
Sep 16 Javascript
Vue3.0的优化总结
Oct 16 Javascript
Vue操作Storage本地化存储
Apr 29 Vue.js
Vue项目中使用flow做类型检测的方法
Mar 18 #Javascript
JavaScript正则表达式验证登录实例
Mar 18 #Javascript
JS正则表达式验证密码强度
Mar 18 #Javascript
原生js实现密码强度验证功能
Mar 18 #Javascript
JavaScript实现密码强度实时验证
Mar 18 #Javascript
js如何验证密码强度
Mar 18 #Javascript
js验证密码强度解析
Mar 18 #Javascript
You might like
解析PHP中数组元素升序、降序以及重新排序的函数
2013/06/20 PHP
Youku 视频绝对地址获取的方法详解
2013/06/26 PHP
php图片水印添加、压缩、剪切的封装类实现
2020/04/18 PHP
一个非常实用的php文件上传类
2017/07/04 PHP
php设计模式之策略模式应用案例详解
2019/06/17 PHP
php慢查询日志和错误日志使用详解
2021/02/27 PHP
接收键盘指令的脚本
2006/06/26 Javascript
用jquery中插件dialog实现弹框效果实例代码
2013/11/15 Javascript
jQuery源码解读之addClass()方法分析
2015/02/20 Javascript
JS实现简单的图书馆享元模式实例
2015/06/30 Javascript
Bootstrap模态框调用功能实现方法
2016/09/19 Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
2017/01/12 Javascript
JS中的三个循环小结
2017/06/20 Javascript
微信小程序图片自适应支持多图实例详解
2017/06/21 Javascript
React应用中使用Bootstrap的方法
2017/08/15 Javascript
vuex实现的简单购物车功能示例
2019/02/13 Javascript
vue vant Area组件使用详解
2019/12/09 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
Vue this.$router.push(参数)实现页面跳转操作
2020/09/09 Javascript
[01:36:19]Secret vs NB 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python数据处理实战(必看篇)
2017/06/11 Python
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
Python爬虫实战之12306抢票开源
2019/01/24 Python
​如何愉快地迁移到 Python 3
2019/04/28 Python
浅谈django2.0 ForeignKey参数的变化
2019/08/06 Python
对Python获取屏幕截图的4种方法详解
2019/08/27 Python
Django框架下静态模板的继承操作示例
2019/11/08 Python
通过python-pptx模块操作ppt文件的方法
2020/12/26 Python
美国儿童运动鞋和服装零售商:Kids Foot Locker
2017/08/05 全球购物
美国家居装饰和豪华家具购物网站:One Kings Lane
2018/12/24 全球购物
对象的序列化(serialization)类是面向流的,应如何将对象写入到随机存取文件中
2015/06/22 面试题
预备党员思想汇报范文
2014/01/11 职场文书
工商管理专业大学生职业生涯规划范文
2014/03/09 职场文书
企业理念标语
2014/06/09 职场文书
运动会通讯稿200字
2015/07/20 职场文书
只需要100行Python代码就可以实现的贪吃蛇小游戏
2021/05/27 Python