redux-form(V7.4.2)笔记(三)之Flow简介

为什么要学习redux-form?

我们知道,react-redux为React开发提供了科学的存储管理方案。另一方面,类似Semantic-UI与Material UI,Ant-UI等则提供了比较全面的基于React组件框架的UI解决方案。但问题在于,后者提供的UI方案还有很大的局限性,特别是对于form表单的各种应用需求支持方面。为此,相对于简单的表单应用,为了减少重复冗余的代码,我们可以去使用redux-form-utils库,此库能利用高阶组件的特性为表单的每个字段提供value和onChange等必须值,而无需你手动创建。但是,对于复杂的表单,redux-form-utils库显得捉襟见肘;此时,转而利用redux-form即成为最佳方案。这是因为redux-form库除了提供表单必须的字段支持外,redux-form还能实现表单同步验证、异步验证甚至嵌套表单等复杂功能。

Javascript静态类型检查工具Flow

为什么存在和要使用Flow?要回答这个问题必须提起微软的TypeScript语言。一提起TypeScript,还不得不提起微软的JScript。JScript是由微软公司开发的活动脚本语言,是微软对ECMAScript规范的实现。JScript最初是随Internet Explorer 3.0于1996年8月发布。在网络程序员谈论Internet Explorer中的JavaScript的时候,他们实际上是指JScript。和其他活动脚本一样,它后来也被Windows Script Host(WSH)和Active Server Pages所支持。典型的JScript源文件使用的扩展名是.js。JScript最新的版本是基于尚未定稿的ECMAScript4.0版规范的JScript .NET,并且可以在微软的.Net环境下编译。JScript在ECMA的规范上增加了许多特性。

TypeScript 是一种由微软开发的自由和开源的编程语言,它是JavaScript的一个超集,扩展了JavaScript的语法。现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。

Flow是个JavaScript的静态类型检查工具,由Facebook出品的开源码项目,问世只有一年多,是个相当年轻的项目。简单来说,它是对比TypeScript语言的解决方式。Flow本质上也只是个检查工具,它并不会自动修正代码中的错误,也不会强制说你没按照它的警告消息修正,就不会让你运行程序。当然,并没有要求什么时候一定要用这类的工具,只是这种作法可以让你的代码更具强健性与提高阅读性,也可以直接避去很多不必要的数据类型使用上的问题,这种开发方式目前在许多框架与函数库项目,或是以JavaScript应用为主的开发团队中都已经都是必用工具。

JavaScript是一种弱(动态)数据类型的语言,弱(动态)数据类型代表在代码中,变量或常量会自动依照赋值变更数据类型,而且类型种类也很少,这是直译式脚本语言的常见特性,但有可能是优点也是很大的缺点。优点是容易学习与使用,缺点是像开发者经常会因为赋值或传值的类型错误,造成不如预期的结果。有些时候在使用框架或函数库时,如果没有仔细看文件,亦或是文件写得不清不楚,也容易造成误用的情况。

这个缺点在应用规模化时,会显得更加严重。我们在开发团队的协同时,一般都是用详尽的文字说明,来降低这个问题的发生,但JS语言本身无法有效阻止这些问题。而且说明文件也需要花时间额外编写,其他的开发者阅读也需要花时间。在现今预先编译器流行的年代,像TypeScript这样的强(静态)类的JavaScript超集语言就开始流行,用严格的角度,以JavaScript语言为基底,来重新打造另一套具有强(静态)类型特性的语言,就如同Java或C#这些语言一样,这也是为什么TypeScript称自己是企业级的开发JavaScript解决方案。

TypeScript自然有它的市场,但它有一些明显的问题,首先是JavaScript开发者需要再进一步学习,内容不少,也有一定陡峭的学习曲线,不过这还算小事情。重大的事情是需要把已经在使用的应用代码,都要整个改用TypeScript代码语法,才能发挥完整的功用。这对很多已经有内部代码库的大型应用开发团队而言,将会是个重大的决定,因为如果不往全面重构的路走,将无法发挥强(静态)类型语言的最大效用。

所以许多现行的开源码函数库或框架,并不会直接使用TypeScript作为代码的语言,另一方面当然因为是TypeScript并非普及到一定程度的语言,社群上有热爱的粉丝也有不是那么支持的反对者。当然,TypeScript也有它的优势,自从TypeScript提出了DefinitelyTyped的解决方式之后,让现有的函数库能额外再定义出里面使用的类型,这也是另一个可以与现有框架与库相整合的方案,这让许多函数库与框架都提交定义档案,提供了另一种选择。另一个优势是,TypeScript也是个活跃的开源码项目,发展到现在也有一段时间,算是逐渐成熟的项目。它的背后有微软公司的支持,在最近发布的知名的、全新打造过的Angular2框架中(由Google主导),也采用了TypeScript作为基础的开发语言。

现在,Flow提供了另一个新的选项,它是一种强(静态)类型的辅助检查工具。Flow的功能是让现有的JavaScript语法可以事先作类型的声明(定义),在开发过程中进行自动检查,当然在最后编译时,一样可以用babel工具来移除这些标记。

相较于TypeScript是另外重新制定一套语言,最后再经过编译为JavaScript代码来运行。Flow走的则是非强制与非侵入性的路线。Flow的优点是易学易用,它的学习曲线没有TypeScript来得高,虽然内容也很多,但大概一天之内学个大概,就可以渐进式地开始使用。而且因为Flow从头到尾只是个检查工具,并不是新的程序语言或超集语言,所以它可以与各种现有的JavaScript代码兼容,如果你哪天不想用了,就去除掉标记就是回到原来的代码,没什么负担。当然,Flow的功用可能无法像TypeScript这么全面性,也不可能改变要作某些事情的语法结构。

redux-form支持基于Flow的静态类型检查

当你从redux-form库中使用import语句导入组件或者函数时Flow能够自动导入相应的类型。而且,你还可以把redux-form提供的所有props类型导入到你的组件中。

有关在JS项目下Flow的安装,请参考文后的文档,在此省略。如果你在配置文件.flowconfig中忽略node_modules文件夹的话,相应的类型不会导入,而且你还会接收到错误提示,如下所示:

import { Field, reduxForm } from 'redux-form'
^^^^^^^^^^^^ redux-form. Required module not found
因此,在你的文件.flowconfig中,请确保整个文件夹不被忽略:
...
[ignore]
<PROJECT_ROOT>/node_modules/editions # you can still selectively ignore packages that cause flow errors
[include]

有关Props类型的简单使用举例

下面的几个例子展示了如何基于Flow在redux-form项目中把相应的类型支持注入到你的使用reduxForm()这个高阶组件(HOC)封装的表单组件中。

使用FormProps举例

import type { FormProps } from 'redux-form'

type Props = {
  someCustomThing: string
} & FormProps
// ^^^^^^^^^^

class MyForm extends React.Component {
  props: Props

  render() {
    const { handleSubmit, someCustomThing } = this.props
    return <form onSubmit={handleSubmit}>// fields here</form>
  }
}

使用FieldProps举例

import type { FieldProps } from 'redux-form'

const renderField = ({ input, meta, ...rest } : FieldProps) =>
//                                           ^^^^^^^^^^^^^
  <div>
    <input {...input} {...rest}/>
    {meta.touched && meta.error && <div>{meta.error}</div>}
  </div>

...

<Field name="myField" component={renderField}/>

使用FieldsProps

import type { FieldsProps } from 'redux-form'

const renderField = (fields : FieldsProps) =>
//                         ^^^^^^^^^^^^^^
  <div>
    {fields.map(({ input, meta, ...rest }) =>
      <div>
        <input {...input} {...rest}/>
        {meta.touched && meta.error && <div>{meta.error}</div>}
      </div>)
    }
  </div>

...

<Fields names={[ 'firstField', 'secondField' ]} component={renderFields}/>

使用FieldArrayProps举例

import type { FieldArrayProps } from 'redux-form'

const renderFieldArray = ({ fields } : FieldArrayProps) =>
//                             ^^^^^^^^^^^^^^^^^^
  <ul>
    {fields.map((name, index, fields) => (
      <li key={index}>
        <Field
          name={`${name}.firstName`}
          type="text"
          component={renderField}
          label="First Name"/>
        <Field
          name={`${name}.lastName`}
          type="text"
          component={renderField}
          label="Last Name"/>
      </li>
    ))}
  </ul>

...

<FieldArray name="contacts" component={renderFieldArray}/>

小结

正如前面提及的,在小型JavaScript项目中,如果你有把握,可以省略使用Flow。尽管如此,但是事实证明,只要你选择使用js开发,主动使用Flow将会为你带来很多的惊喜——这远大于你学习Flow的时间投入。在基于React的redux-form子项目开发中,上述结论也不例外。

参考资料

1.http://www.voidcn.com/article/p-mchkxlor-e.html
2.https://redux-form.com/7.4.2/docs/flow.md/
3.https://flow.org/en/docs/usage/
4.http://www.voidcn.com/article/p-miducqxo-d.html
5.http://www.voidcn.com/article/p-cpvljgnq-bmq.html

相关文章
相关标签/搜索