Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 表单设计 及 通用模式、组件抽取 #194

Open
EthanLin-TWer opened this issue Jan 13, 2018 · 0 comments
Open

React 表单设计 及 通用模式、组件抽取 #194

EthanLin-TWer opened this issue Jan 13, 2018 · 0 comments

Comments

@EthanLin-TWer
Copy link
Owner

EthanLin-TWer commented Jan 13, 2018

image

React 表单设计

一份表单设计,其他涉及众多的细节。如果单独处理,无疑什么繁琐,充满众多细节。而其实上,作为「填表单」这个行为,它定制的部分却往往不多,比如使用者只需要关注「验证逻辑」、「显示什么错误信息」等高层的东西,而底层的行为和细节代码我们希望不需要过多关注。这样,「表单」就具有了一些逻辑上的共性,可以把这些东西抽取出来,封装成为组件,然后让使用者只需要关注高层的东西(逻辑、错误信息、验证方式等)。

基于这个考虑,「表单填写」这个场景有哪些细节需要考虑呢?不同的细节决定了怎样不同的技术实现方式呢?高层需要考虑的东西可以简化成什么呢?

基本问题

  • 支持表单纯净性检查(pristine)
  • 支持基本的验证功能(validation callback): f(data) => errorMessage
  • 支持基本的提交表单时验证功能(submit)
  • 支持传出表单当前状态(已填数据、错误信息)

更细节问题

  • 是否需要支持错误信息精确到字段级别?这可能有几种场景,但基本都是一个字段的(业务)合法性不能在填写当时验证(需要结合其他数据进行验证):
    • 比如在填 B 字段的时候需要 A 字段数据,此时校验发现 A 字段是业务错误的,那么需要将字段 A 标红
    • 比如在提交整个表单的时候发现 A 字段业务不合法,提示错误信息,并将其标红
  • 是否需要支持字段的异步(后端)验证?提交时进行后端这是可以理解的,问题是字段级别是否也需要进行异步验证?这会关系到组件设计和应用架构的问题(错误信息是在哪管理,api 在哪里调用)

技术支持

下面谈谈这几种场景所需要的解决方案。

  • pristine 纯净性检查:很简单。默认内置支持即可
  • 基本的验证功能:很简单,提供一个 onValidate 即可,因为这里需要支持定制化的点就是这个 validator:validate(data) => errorMessage。它需要实现这个契约
  • 基本的提交表单时验证功能:很简单,提供一个 onSubmit 方法即可,这也是需要支持定制化的点
  • 基本的表单当前状态维护:很简单,提供一个什么接口传出来即可。什么时候需要数据就什么时候传出来,错误信息同理
  • 支持字段级别的错误定位:这个需要提供一个表单级别的 wrapper,由它来管理所有字段所产生的 error,由于有不同字段,肯定又需要 key 来区分,因此,这个从技术上需要两个东西:
    • 提供 Form 表单级别的组件,它会通过某种契约知晓、控制组件之间的状态(显示、错误信息、数据、是否禁用等)
    • 提供 Field 字段级别的组件,它需要实现某种契约,与 Form 组件通晓状态

比较难缠的是字段的异步(后端)验证这个问题。一般来说,表单的验证分为两种,一种是表单级别的验证,这种验证一定要通过后端验证;另一种是字段级别的验证,这种验证既可以使用前端验证,也可以使用后端验证。

其中,字段的前端验证,其实就是前面提供的 onValidate 接口,该种验证是同步完成的,通常速度极快,多只是校验表单数据是否为空,长度是否过长等「格式」上的问题。这种验证方式下,出错信息可以直接反映到字段上,通常来说,出错信息也是存储在组件的 state 中即可。

为字段验证带来挑战的是后端验证方式。由于需要走一趟后端,所以必然要调一趟 API,再从 API 的结果来确定是否有出错信息、出错信息是什么。而一般而言,我们的出错信息是在组件的 state 中管理的,而一般来说 API 作为有副作用的行为,发生地都在 redux/saga 中,最后必然是从 props 这种进来。那么,如何管理这两个不同的数据源?策略无外乎三种:

  • 统一数据源到组件内部 state。这使得 API 必须写到组件内部,而非 thunk/saga 等专门管理的工具,不利于架构可追溯状态的应用,一定程度上违背了 react/redux 应用的架构和设计原则
  • 统一数据源到 redux 并作为 props 使用。这解决了上一点的架构问题,但使得本来非常简单的 字段前端验证 校验也必须放到 redux 中做,使这部分校验变重了,也失去了一些可读性
  • 不统一数据源,组件接受 props 和 state 产生的错误信息。这样必须还必须在组件内部「以某种形式管理」这两份错误信息,而这个管理方式就需要使用者来定制,并且还需要知道本来仅由 Validator 管理的 error message 的细节及其契约,API 就很不友好,也非常不组件化

API

综上,作为表单的设计者,在获得一个满意的解决方案前,你需要问自己,自己的表单复杂性有多高?是否需要支持字段级别的后端验证?是否需要支持跨字段的验证?是否需要定制 UI?有了确定的答案后,你才能知道这个表单需要什么技术支持、是否需要引入三方库,以及如何选择合适的三方库等。

三方库

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant