Flow定义
Flow是JavaScript
的类型检查器,使得写代码的效率更高效,Vue.js
的源码利用了 Flow
做了静态类型检查,所以了解 Flow
有助于我们阅读源码
添加类型注解的方式标记代码变量或参数的类型
Flow安装使用
-
yarn init --yes
初始化项目 -
yarn add flow-bin --dev
flow类型检查模块 -
js
文件开头需添加@flow注解 - 关闭
vsCode JS
校验javascript:validate
-
yarn flow init
创建.flowconfig
配置文件 - 执行
yarn flow
编译
运行时移除类型注解
-
使用官方
flow-remove-types
工具安装
yarn add flow-remove-types --dev
创建
src
目录yarn flow-remove-types src -d dist
-
使用
babel
配合flow
转换插件安装
yarn add @babel/core @babel/cli @babel/preset-flow --dev
.babelrc
文件中添加presets:[@babel/preset-flow]
yarn babel src -d dist
开发插件(Flow language Support)
官方插件
类型推断
// @flow
// 通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型
function square (n) {
return n * n
}
// square('100')
square(100)
类型注解
// @flow
// 事先注释好我们期待的类型,Flow 会基于这些注释来判断
function square (n: number) {
return n * n
}
let num: number = 100
// num = 'string' // error
function foo (): number {
return 100 // ok
// return 'string' // error
}
function bar (): void {
// return undefined
}
原始类型
// flow
const a: string = 'foobar'
const b: number = Infinity // NaN // 100
const c: boolean = false // true
const d: null = null
const e: void = undefined
const f: symbol = Symbol()
数组类型
// @flow
const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 2, 3]
// 元组
const foo: [string, number] = ['foo', 100]
对象类型
const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 }
const obj2: { foo?: string, bar: number } = { bar: 100 }
// 可添加任意个数的键和值 但必须都是字符串
const obj3: { [string]: string } = {}
obj3.key1 = 'value1'
obj3.key2 = 'value2'
函数类型
// @flow
function foo (callback: (string, number) => void) {
callback('string', 100)
}
foo(function (str, n) {
// str => string
// n => number
})
特殊类型
// 字面量类型
const a: 'foo' = 'foo'
const type: 'success' | 'warning' | 'danger' = 'success'
// 声明类型
type StringOrNumber = string | number
const b: StringOrNumber = 'string' // 100
// Maybe 类型
const gender: ?number = undefined
// 相当于
// const gender: number | null | void = undefined
Mixed和any
// @flow
// Mixed类型为具体类型 安全的 如果未标明是哪个类型 无法调用具体方法
function passMixed (value: mixed) {
if (typeof value === 'string') {
value.substr(1)
}
if (typeof value === 'number') {
value * value
}
}
passMixed('string')
passMixed(100)
// any是弱类型 不安全的 直接调用方法不会报错
function passAny (value: any) {
value.substr(1)
value * value
}
passAny('string')
passAny(100)
运行环境API
// @flow
// 如果查到返回HTMLElement 查询不到返回null
// document.getElementById('app') 必须传入字符串
const element: HTMLElement | null = document.getElementById('app')
FLow
在Vue.js
源码中的应用
-
libdef
概念包含第三方库声明的
JS
文件简称,可以用于识别第三方库或者自定义类型;不然引入的第三方库,Flow
检查时会抛出错误// @flow ... const s = $('id').hide() // 由于Flow并不认识$, 所以会报错,此时需要引入jQuery的库定义 ...
-
使用
flow-typed
解决- 通过
yarn add flow-typed
安装flow-typed
仓库,包含众多流行的第三方库的libdef
- 在项目根目录下创建flow-typed文件,并且下载对应的定义文件
- 运行
flow-typed install
检查package.json
文件,下载项目中用到的第三方库的libdef
- 下载完成,
yarn flow
就没有错误了 - 如果用的库在
flow-typed
找不到,需要自定义libdef
- 通过
-
Vue.js
源码主目录的
.flowconfig
文件,是Flow
的配置文件,Vue.js
自定义类型都在里面定义。[libs]
用来描述包含指定库定义的目录,默认是flow-typed
目录,Vue.js
指定未flow
,表示指定的库定义在flow
文件夹,目录如下:flow ├── compiler.js # 编译相关 ├── component.js # 组件数据结构 ├── global-api.js # Global API 结构 ├── modules.js # 第三方库定义 ├── options.js # 选项相关 ├── ssr.js # 服务端渲染相关 ├── vnode.js # 虚拟 node 相关
Vue.js
自定义类型都定义在这里,遇到看不懂的类型,就需要翻阅这些数据结构的定义。