随手打开一个网页,输入’Vue源码’各种五花八门的介绍都能让你或多或少的理解一些。但多数时候我们都停在了"use"这个阶段。举一个很简单的例子,一个中量级的Vue项目多人合作开发。然后统一的代码风格,愉快的开发过程。在一段时间的手舞足蹈后有人掉队了。回头看看接手的变成你一个人了,内心窃喜(成果都是我的了)
但常年的快速开发让你也很敏感(接手==
接锅)!!!
打开前几个社畜的模块你发现了很多不好的习惯例如 props [XX], "==
"诸如此类的写法。手起刀落你开始正篇幅的找然后开始改。改完了编辑器没有黄色警告了 你长舒一口气!!
出于谨慎你开始跑起来项目,一个个模块的功能都看了看(嗯嗯一起安好~~)。嗯?怎么回事!
是出问题了?小心翼翼的打开F12,没有黄,红但为啥就不是期待的结果呢
this[`economyView${item}`].scale===0
进入这个判断条件没错啊!再看看历史this[
economyView${item}].scale==0
是的 ,只是强迫症加严格模式让你很自然的改了条件的判断符号!原来的scale是一个string! 但是你的同胞将它写成了Number但基于我们的JavaScript 是动态类型语⾔。没有强制的类型校验这个隐秘的问题就出现了!生产环境中诸如此类的问题在不加追踪的情况下会有很多。所以我们要试着改变一下自己!
开启我们Vue源码的第一段故事 Flow
Flow 是 facebook 出品的 JavaScript 静态类型检查⼯具。Vue.js 的源码利⽤了 Flow 做了静态类型检查
认识它之前我们再回顾一下我们的吃饭的家伙!**JavaScript **
JavaScript 是动态类型语⾔,它的灵活性有⽬共睹,但是过于灵活的副作⽤是很容易就写出⾮常隐蔽的 隐患代码,在编译期甚⾄看上去都不会报错,但在运⾏阶段就可能出现各种奇怪的 bug
Flow 的⼯作行为方式
通常类型检查分成 2 种⽅式:
类型推断:通过变量的使⽤上下⽂来推断出变量类型,然后根据这些推断来检查类型。
类型注释:事先注释好我们期待的类型,Flow 会基于这些注释来判断。
1.类型注释
类型推断是 Flow 最有⽤的特性之⼀,不需要编写类型注释就能获取有⽤的反馈。但在某些 特定的场景下,添加类型注释可以提供更好更明确的检查依据。
function TestSplit(string) {
return string.split(',')
}
Testsplit(23)
Flow 检查上述代码后会报错,因为函数 TestSplit期待的参数是字符串,⽽我们输⼊了数字。
2.类型注释
类型推断是 Flow 最有⽤的特性之⼀,不需要编写类型注释就能获取有⽤的反馈。但在某些 特定的场景下,添加类型注释可以提供更好更明确的检查依据
function TestAdd(a, b){
return a + b
}
TestAdd('test', 12)
Flow 检查上述代码时检查不出任何错误,因为从语法层⾯考虑, + 即可以⽤在字符串上,也可以⽤ 在数字上,我们并没有明确指出 TestAdd() 的参数必须为数字。
上述情况下,我们可以借助类型注释来指明期望的类型。类型注释是以冒号 : 开头,可以在函数 参数,返回值,变量声明中使⽤
function TestAdd(a: number, b: number): number {
return a + b
}
TestAdd('test', 12)
现在 Flow 就能检查出错误,因为函数参数的期待类型为数字,⽽我们提供了字符串。 上⾯的例⼦是针对函数的类型注释。接下来我们来看看 Flow 能⽀持的⼀些常⻅的类型注释。
3.数组检查
let arr: Array<number> = [2, 3, 4]
arr.push('test')
数组类型注释的格式是 Array , T 表⽰数组中每项的数据类型。在上述代码中,arr 是每项均为 数字的数组。如果我们给这个数组添加了⼀个字符串,Flow 能检查出错误
4.类和对象检查
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)
}
类的类型注释格式如上,可以对类⾃⾝的属性做类型检查,也可以对构造函数的参数做类型检查。这 ⾥需要注意的是,属性 y 的类型中间⽤ | 做间隔,表⽰ y 的类型即可以是字符串也可以是数 字。 对象的注释类型类似于类,需要指定对象属性的类型。
5.Null
若想任意类型 T 可以为 null 或者 undefined ,只需类似如下写成 ?T 的格式即可
var foo: ?string = null
Flow 在 Vue.js 源码中的应⽤
有时候我们想引⽤第三⽅库,或者⾃定义⼀些类型,但 Flow 并不认识,因此检查的时候会报错。为了 解决这类问题,Flow 提出了⼀个 libdef 的概念,可以⽤来识别这些第三⽅库或者是⾃定义类型, ⽽ Vue.js 也利⽤了这⼀特性。
在Vue.js的主要目录下有.flowconfig文件,它是Flow的配置文件。其中[libs]部分用了描述包含指定库定义的目录,初始的名为‘flow-type’
flow
├── compiler.js # 编译相关
├── component.js # 组件数据结构
├── global-api.js # Global API 结构
├── modules.js # 第三⽅库定义
├── options.js # 选项相关
├── ssr.js # 服务端渲染相关
├── vnode.js # 虚拟 node 相关