认识 Flow

Flow 是 facebook 出品的 JavaScript 静态类型检查⼯具。Vue.js 的源码利⽤了 Flow 做了静态类型检查, 所以了解 Flow 有助于我们阅读源码

Flow 的官方文档

为什么⽤ Flow

JavaScript 是动态类型语⾔,它的灵活性有⽬共睹,但是过于灵活的副作⽤是很容易就写出⾮常隐蔽的 隐患代码,在编译期甚⾄看上去都不会报错,但在运⾏阶段就可能出现各种奇怪的 bug。

类型检查是当前动态类型语⾔的发展趋势,所谓类型检查,就是在编译期尽早发现(由类型错误引起 的)bug,⼜不影响代码运⾏(不需要运⾏时动态检查类型),使编写 JavaScript 具有和编写 Java 等强 类型语⾔相近的体验。

项⽬越复杂就越需要通过⼯具的⼿段来保证项⽬的维护性和增强代码的可读性。 Vue.js 在做 2.0 重构的 时候,在 ES2015 的基础上,除了 ESLint 保证代码⻛格之外,也引⼊了 Flow 做静态类型检查。

之所以 选择 Flow,主要是因为 Babel 和 ESLint 都有对应的 Flow 插件以⽀持语法,可以完全沿⽤现有的构建 配置,⾮常⼩成本的改动就可以拥有静态类型检查的能⼒。

Flow 的⼯作⽅式

通常类型检查分成 2 种⽅式:

类型推断:通过变量的使⽤上下⽂来推断出变量类型,然后根据这些推断来检查类型。它不需要任何代码修改即可进⾏类型检查,最⼩化开发者的⼯作量。它不会强制你改变开发习惯,因 为它会⾃动推断出变量的类型。

这就是所谓的类型推断,Flow 最重要的特性之⼀。 通过⼀个简单例⼦说明⼀下

/*@flow*/``
function split(str) {
return str.split(' ')
}
split(11) // 会报错:str.split is not a function // Flow 检查上述代码后会报错,因为函数 split 期待的参数是字符串,⽽我们输⼊了数字

类型注释:事先注释好我们期待的类型,Flow 会基于这些注释来判断。

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

/*@flow*/
function add(x, y){
return x + y
}
add('Hello', 11)

Flow 检查上述代码时检查不出任何错误,因为从语法层⾯考虑, + 即可以⽤在字符串上,也可以⽤ 在数字上,我们并没有明确指出 add() 的参数必须为数字。 在这种情况下,我们可以借助类型注释来指明期望的类型。

类型注释是以冒号 : 开头,可以在函数 参数,返回值,变量声明中使⽤。 如果我们在上段代码中添加类型注释,就会变成如下

/*@flow*/

function add(x:number, y:number): number{
return x + y
}
add(11, 11)

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

上面的例子是针对函数的类型注释。接下来我们来看看 Flow 能支持的一些常见的类型注释。

数组:数组类型注释的格式是 Array<T>T 表示数组中每项的数据类型。在上述代码中,arr 是每项均为数字的数组。如果我们给这个数组添加了一个字符串,Flow 能检查出错误

/*@flow*/

var arr: Array<number> = [1, 2, 3]
arr.push('Hello')

类和对象:类的类型注释格式如上,可以对类自身的属性做类型检查,也可以对构造函数的参数做类型检查。这里需要注意的是,属性 y 的类型中间用 | 做间隔,表示 y 的类型即可以是字符串也可以是数字。

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

/*@flow*/

class Bar {
x: string; // x 是字符串
y: string | number; // y 可以是字符串或者数字
z: boolean; constructor(x: string, y: string | number) {
this.x = x
this.y = y
this.z = false
}
} var bar: Bar = new Bar('hello', 4) var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
a: 'hello',
b: 11,
c: ['hello', 'world'],
d: new Bar('hello', 3)
}

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

/*@flow*/

var foo: ?string = null // 此时,foo 可以为字符串,也可以为 null

Flow 在 Vue.js 源码中的应用

有时候我们想引用第三方库,或者自定义一些类型,但 Flow 并不认识,因此检查的时候会报错。为了解决这类问题,Flow 提出了一个 libdef 的概念,可以用来识别这些第三方库或者是自定义类型,而 Vue.js 也利用了这一特性。

在 Vue.js 的主目录下有 .flowconfig 文件, 它是 Flow 的配置文件

这其中的 [libs] 部分用来描述包含指定库定义的目录,默认是名为 flow-typed 的目录。

这里 [libs] 配置的是 flow,表示指定的库定义都在 flow 文件夹内。我们打开这个目录,会发现文件如下

flow
├── compiler.js # 编译相关
├── component.js # 组件数据结构
├── global-api.js # Global API 结构
├── modules.js # 第三方库定义
├── options.js # 选项相关
├── ssr.js # 服务端渲染相关
├── vnode.js # 虚拟 node 相关
												

vue源码分析—认识 Flow的更多相关文章

  1. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  2. vue 快速入门 系列 —— 侦测数据的变化 - [vue 源码分析]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue 源码分析] 本文将 vue 中与数据侦测相关的源码摘了出来,配合上文(侦测数据的变化 - [基本实现]) 一起来分析一下 vue ...

  3. 前端Vue 源码分析-逻辑层

    Vue 源码分析-逻辑层 预期的效果: 监听input的输入,input在输入的时候,会触发 watch与computed函数,并且会更新原始的input的数值.所以直接跟input相关的处理就有3处 ...

  4. [Vue源码分析] v-model实现原理

    最近小组有个关于vue源码分析的分享会,提前准备一下… 前言:我们都知道使用v-model可以实现数据的双向绑定,及实现数据的变化驱动dom的更新,dom的更新影响数据的变化.那么v-model是怎么 ...

  5. Vue源码分析(一) : new Vue() 做了什么

    Vue源码分析(一) : new Vue() 做了什么 author: @TiffanysBear 在了解new Vue做了什么之前,我们先对Vue源码做一些基础的了解,如果你已经对基础的源码目录设计 ...

  6. vue源码分析—Vue.js 源码目录设计

    Vue.js 的源码都在 src 目录下,其目录结构如下 src ├── compiler # 编译相关 ├── core # 核心代码 ├── platforms # 不同平台的支持 ├── ser ...

  7. Vue 源码分析—— 目录结构

    一,Vue.js 的源码都是在src 目录下,其目录结构如下. 1.compiler 目录包含Vue.js 所有编译相关的代码.它包括把所有模板解析成ast 语法树, ast 语法树优化等功能. 2. ...

  8. vue源码分析—Vue.js 源码构建

    Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下.(Rollup 中文网和英文网) 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.j ...

  9. vue源码分析之new Vue过程

    实例化构造函数 从这里可以看出new Vue实际上是使vue构造函数实例化,然后调用_init方法 _init方法,该方法在 src/core/instance/init.js 中定义 Vue.pro ...

随机推荐

  1. getopt与getopt_long

    如何通过命令行,为程序传入参数,可以使用函数getopt与getopt_long. 函数的声明如下: #include <unistd.h> int getopt(int argc, ch ...

  2. 如何修复使用WSUS进行升级Win 10 更新1809的报错(0x8024200)

    备注:该文档有另一个姊妹篇,介绍如何修复下游服务器一直有处于需要文件下载的状况. /* Style Definitions */ table.MsoNormalTable {mso-style-nam ...

  3. gin+gorm

    在[环境变量]中添加如下[用户变量]/[系统变量]:GO111MODULE,值为on go mod init目录 在项目中新建文件main.go,并添加测试代码 package main import ...

  4. 从0到1打造自己的VOIP网络电话系统(基于FreePBX)

    从0到1打造自己的网络电话系统 最近流量卡越来越便宜了,看看自己手里的"坑不死老用户"的联通卡,顿时感觉到深深的恶意,但是iPhone没有双卡功能,所以只好自己动手打造一个网络电话 ...

  5. Java笔试题库之选题题篇【71-140题】

    71下面哪几个函数是public void method(){̷}的重载函数?() A.public void method( int m){̷} B.public int method(){̷} C ...

  6. 初始hibernate 和环境搭建

    hibernate是一个开源的数据持久化框架. hibernate的优点: hibernate进行操作数据库提高了代码的开发速度,大大降低了代码量,降低了维护成本. hibernate支持许多面向对象 ...

  7. 【Android Studio安装部署系列】三十六、Android studio3.2使用过程中注意事项

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio升级到3.2之后,运行旧项目的时候出现了各种情况,特此记录下. 一.打包选项多了,一般情况下选择APK即 ...

  8. AlertConfirmDialog【基于AlertDialog的确认取消对话框】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 确认取消对话框,基于AlertDialog.不是基于DialogFragment. 按钮文本可以根据实际情况更换. 效果图 代码分析 ...

  9. XPath和CssSelector定位总结

    1. 介绍XPath和CssSelector 2. XPath有哪些方式 2.1 通过XPath语法 2.2 Contains关键字 2.3 Start-With 2.4 Or和And关键字 2.5 ...

  10. jquery快速入门(三)

    捕获内容和属性 1.DOM 操作 获得内容 - text().html() 以及 val() text() - 设置或返回所选元素的文本内容,如果不带值则是返回值,如果带值则是修改值,如:$('p') ...