YSS

Write Less & Do More

Label 项目下的 Popup 改造

前言

我们的 B端项目都是放在 admin-fe 仓库里。

Label 变更的需求是我接手到的第一个需求,所以在正式做需求之前,很有必要先完整的去了解整个项目的运作,以及理解 Label 这块业务的由来。

Admin-FE 项目

整体先过了一遍项目,看看它是怎么本地启动的,入口是怎么去做的,路由层面做了什么样的处理。

通通过来一遍之后就画了一个简单的 admin-fe 的系统架构图。

admin-fe-constructor

整体的理解就是:

  1. Layout 是最外层的入口
  2. 页面上做了大的路由曾经划分,每个大的路由都是异步加载的,通过第一级的 path 做了区分
  3. 每个路由是由一个或多个页面聚合而成的,同一个大路由下的页面基本共用相同的 Model 、Component 和 对应的 API 文件
  4. 之后就是一些公共的模块和库,包括 Hooks、Store、Utils
  5. 最底层就是 React + AntD ,我们所有的内容都是基于 AntD 组件去构建的

熟悉了项目才能更好的去做好开发,写好代码。

但仅仅写代码,好说,但不理解业务,就白忙活了。

所以,我们需要看一下我们做的这个 Label 业务具体是怎么回事。

Label 的理解

Label 我们知道它就是标签的意思,在英文里还有一个单词叫 Tag。

通常来说 Tag 会更细一些。

然后,在我们当前 Video 里的场景来说,Label 具体分为这么几类:

  1. Object Type
  2. Label Type
  3. L1
  4. L2
  5. Attribute
  6. Value

这个版本我们叫它 Label 2.0

那肯定还有之前的一个版本,对,那就是 Label 1.0

Label 1.0

label 1.0 是一个极简单的分类,就是只有两级:L1 、L2

L1 > L2

这里没有什么特别可以说的。那我们看看 Label 2.0

Label 2.0

做 Label 2.0 的目标是要建立一个可扩展的 Label 标签数据体系。能更好的服务于后续的业务发展需要。

它的做法,这张图给出了诠释:

label-2

那怎么理解这些名词呢?

首先,还是保留了分级分类,Object Type 、Label Type 、L1 、L2 就是各个层级的分类

  1. Object Type:可以理解为大的业务线分类
  2. Label Type:基于这个业务下的产品分类,比如:Content Label
  3. L1:能够明确指代某一类事物的分类,比如:Food
  4. L2:具体描述某一种类型的事物分类,比如:Cooking Class

当然,我们也没有必要刻意去抠字眼。

而 Attribute: Value,更多指的是具体标签,比如:手机 Attribute brand,对应的取值有:huawei、apple、xiaomi etc.

总的理解

Label 2.0 是一个集分类和标签为一体的标签数据架构体系。

当我们理解到这一层的时候,其实就已经对整个的 Video Label 体系有了一个整体认识。

那接下来要做的事情就是按照 PRD 的要求去做对应的开发。

开发

之前的做法

之前的做法每个页面都有自己完全独立的 popForm 去承接。

label-3

这就导致了每一个类型都需要一个单独的 popForm,但每个 popForm 里面的内容大致雷同,里面做的事情都一样的。

这样一来,代码就产生了很多的冗余。很多逻辑都没有复用。

对应的,如果产品要改一块逻辑,意味着所有的地方都要去改。

而我这次做的需求就最明显不过了。

这次的需求

这次的需求就是要在 label 所有分类和标签数据层面增加,地区属性,对应的交互上,就是需要把 popForm 这部分从最初的只需要一步就能完成,变成了必须两步才能完成。

继而,不管是交互还是复杂程度都较之前增加了不少。

现实的问题

如果继续按照之前的写法,就意味着我需要一个一个的去修改 popForm。

比较好的做法,应该是先完成一个 popForm ,然后再去把对应的修改逻辑合并到新的 popForm 上。

这种做法看似也能完成这次任务,但是

  1. 可维护性差,一个逻辑有问题,所有的 popForm 都需要去改
  2. 代码冗余,相同的处理代理,存在多个文件里

我的改造

最简单的做法,可能是说依旧沿用现在的方案,然后抽离出一些公共的逻辑及模块。

这样一来,整体看着,是有了改进,有了进步。

但我们是不是还可以有更好的方式呢?

下面就是我给出的一个方案,做一次彻底的拆分和解耦:

label-3

整体思路就两个:

  1. 整体抽象,拆分成各个独立的个体,个体尽可能的完全独立。
  2. 抽离各个模块里,可以通用逻辑,通过通用模块或者 hooks 进行聚合。

具体到上面的架构:

  1. FormItem 是最小粒度的组件,它是一个完全独立的组件,只关注于自身的一个实现逻辑,以及对应的校验规则。
  2. Popup 是把各个 FormItem 进行组合使用的,每个 Popup 可能会用到其中的一个或多个 FormItem ,它不关心里面的逻辑,只是每次点击完成的时候触发 Form 逻辑的检查,最后收集到的 Form 数据做一些必要的转换后传递给 PopupFrom 去使用。
  3. PopupForm 是由两个 Popup 组成,它负责调度不同的 Popup 展示,并且保留各个 Popup 传递给它的数据,最终把所有 Popup 数据混合起来传递给业务。