Flow 在 react 项目中基本使用

版权声明:转载请注明原文地址 https://blog.csdn.net/mjzhang1993/article/details/82692674

Flow 在 react 项目中基本使用

说明

Flow 是一个静态类型检查器,可以在编码时识别问题并快速反馈,它专门为 JavaScript 程序员设计,能够理解常用的 JS 语言及其动态特性,开发时Flow 会给出错误类型提示,但是他不会禁止代码运行

源码

0. 安装及配置

  1. 全局安装 flow-bin
# 全局安装
npm install -g flow-bin
  1. 根文件夹添加 flow 配置文件 .flowconfig
  2. 需要做类型检查的文件中 增加 // @flow 标识
  3. webStorm 中使用:进入 Preferences | Languages & Frameworks | JavaScript 配置 language version 为 Flow 就可以了
  4. vscode 中直接下载插件 Flow Language Support 即可

1. .flowconfig 配置文件说明

[ignore] # 忽略的不需要检查的文件
<PROJECT_ROOT>/node_modules/.*
# <PROJECT_ROOT> 表示根目录的绝对路径

[include] # 表示待检测的路径, .flowconfig 所在目录下的所有文件都被认为是待检测的 

[libs] # 指定接口文件的路径
src/interfaces/

[lints]

[options] # 设置配置项
module.name_mapper='^.*\.less$' -> 'css-module-flow' # 解决flow查找样式出错

[strict]

2. 启动对代码的检查

代码第一行加上 // @flow 的注释,这样 flow 就会检查这个文件了

// @flow

3. 类型注释 annotations

  1. 类型注解通常以 : 开头,可以用在方法参数和返回值还有变量声明
// @flow

// any 注解表示任意动态类型
function foo(x: number, y: string, z: Array<number | string | Array<any>>): number | null {
   return x * 10 * y .length + z.length;
}

const a = foo(21, '1sss0', [2, 3, 'ssss', ['s']]);
const b: number = 1234;

class Test {
   a: string = 'test a';
   static b: number = 0;

   showArray(a: number): Array<any> {
      return [a, this.a];
   }
}

const test = new Test();

const res = test.showArray(Test.b);

console.log(a, b, res);

4. 弱模式

修改注解为如下,弱模式一样会给出类型错误,但是会给的更少或者更易修复

// @flow weak 

5. 检测第三方模块调用代码(项目引用外部资源时如何使用 Flow)

接口文件,Flow 支持接口文件,目的是帮助 Flow 理解第三方的代码,这些文件定义了一个第三方模块的的接口,包括类型,他同时又跟第三方源码分离,不需要改变第三方文件,接口文件只是用来定义类型检查

  1. 不需要动第三方源码
  2. 编写接口文件,用来给第三方库做类型检查,
  3. .flowconfig 配置文件中指明使用这些接口文件
[ignore]

[include]

[libs] # 引入需要的接口文件
src/interfaces/

[lints]

[options]
module.name_mapper='^.*\.less$' -> 'css-module-flow'

[strict]
  1. 接口文件样式
declare var DEBUG: bool; // 声明一个全局变量类型
declare function isLeapYear(year: string): bool; // 全局函数

// 声明模块由命名模块和声明导出模块组成,导出的可以是变量、函数、类等
declare module Misc {
    declare var DEBUG: bool;
}
declare module 'immutable' {
    declare var exports: $Exports<'immutable'>;
}

6. 类型注释中可以包括的类型

JavaScript 原生数据类型, Flow 基本都有,但是可以使用小写,例如:js 中 Number flow 中 number, 如果使用 Number 这类 表示传入的值要是一个 Number 类型的对象,如果传入的是数值会报错,如果使用 number 则传入 数值即可

  1. boolean
  2. number
  3. string
  4. null
  5. void 对应 undefined
  6. any 表示任意类型 mixed 类似
  7. Array 数组类型, 其中 T 用来描述数组中值得类型
  8. Object
  9. Function
  10. 可以使用自定义的类来注释

可以使用 | 表示或者 使用 & 表示并且
可以通过 ? 定义可选值,如下

function test(a: ?string, b?: number) {
    // a: ?string 表示属性值不一定是 string 也可以是 null undefined
    // b?: number 表示属性可有可无
}

7. class 中使用

flow 支持对 es6 的类进行标注,包括类的属性和方法,类中的属性必须额外添加类型标注,并且要与方法同一层

// @flow

class P {
   name: number; // 类中的属性需要在与方法同一级添加类型标注
   constructor(name) {
      this.name = name;
   }
}

class Parent {
   name: string;
   constructor(name: string) {
      this.name = name;
   }
}

class Child extends Parent {
   constructor(name) {
      super(name);
   }
}

const c: Parent = new Child('sss'); // 使用类判断类型

console.log(c.name);

8. interface 接口

如果 两个 class 的结构类似,那么对应的实例如果想在类型判断时为相同,那么可以使用 interface 声明一个接口

// @flow

interface PP {
   name: string;
   read(): string;
}

class P {
   name: string;
   constructor(name: string) {
      this.name = name;
   }
   read(): string {
      return this.name;
   }
}

class Parent {
   name: string;
   constructor(name: string) {
      this.name = name;
   }
   read(): string {
      return this.name;
   }
}


const p: PP = new Parent('sss');

console.log(p.read());

9. 使用 type 定义自定义的类型


// type 定义的类型不仅可以是对象,也可以是数组或者字符串等
type Parent = {
   name: string,
   age: number
}


const p: Parent = {
   name: 'xxx',
   age: 90
};

10. React 中使用

    // 无状态组件
    const Button = (props: {text: string}) => (<button>{props.text}</button>)  

    // 一般组件

    // 定义 Props 类型
    type Props = {
       changeInputInfo: Function,
       inputInfo: Map<string, any>,
       postNewInfo: Function
    }

    type State = {
        test: number
    }

    export default class NewMember extends React.PureComponent<Props, State> {
        // 挂在到 this 下的属性要在这里提前声明类型
        state: State;
       constructor(props: Props) {
          super(props);
          this.state = {
            test: 0
          };
       }
       handleChange(mold: string, e: any): void {
          const { changeInputInfo, inputInfo } = this.props;
          const newInfo = inputInfo.set(mold, e.target.value);

          changeInputInfo(newInfo);
       }
       handleClick = () => {
          const { postNewInfo, inputInfo } = this.props;

          postNewInfo(inputInfo)
             .then(res => console.log('success return ', res))
             .catch(err => console.error(err));
       };
       render(): React.Element<any> {
          const inputInfo = this.props.inputInfo;
          const test = this.state.test;

          return (
             <div className="new-member">
                <p>
                   姓名:
                   <input type="text" value={inputInfo.get('name')} onChange={this.handleChange.bind(this, 'name')} />
                </p>
                <p>
                   电话:
                   <input type="tel" value={inputInfo.get('tel')} onChange={this.handleChange.bind(this, 'tel')} />
                </p>
                <button onClick={this.handleClick}>提交 {test}</button>
             </div>
          );
       }
    }

猜你喜欢

转载自blog.csdn.net/mjzhang1993/article/details/82692674