这段时间项目迭代比较快,所以很多时候对于记录的状态和类型判断我都是使用的 魔术字符串 的形式,但是这样就与代码形成了 “强耦合”, 不利于后期的维护。
例如这样的代码结构:
1 | <!-- 用vue template来举例 --> |
特别是最近一整个分类的类型和状态的都变更了,所以在业务逻辑内的魔术字符串也需要一个一个文件去同步修改,大部分的都被替换了,但还有一些零碎的地方没有被修改到,导致不断有 BUG 被提上来,这就很头疼了。
所以我就想者怎么把业务逻辑内的魔术字符串使用一种方式替换掉,最开始我想法是把状态集中起来进行管理
阶段一:使用数组来管理 方式 ①
在数组中枚举所有状态,然后调用数组下标的方式去使用。
例如这个示例:
1 | // order.js |
就可以这样使用 statusLabels[index]
来转换 key
值为 label
,但是这样很明显会有一些问题,比如说:
这个
key
值不能是负数,虽然可以通过下面的方式来处理,但是有点蠢….
如果最小的 key 值 为-2
时,把对应的 状态名 放到数组首位,通过这样转换status[index + 2]
;依旧强耦合,在组件的条件判断中还是会使用 key 值,例如:
<a @click='xxx' v-if='record.status === 0'>编辑</a>
,
如果将来 增加/删除 状态的时候会还是需要一个一个文件修改。只能处理
key - label
的转换,并不能增加其他属性
当然如果单纯只是转换 key
和 label
可以这样使用,这个是项目一开始所使用的方式,后来陆续修改成了 方式 ② 的形式。
阶段二:数组管理 方式 ②
这个阶段因为很多组件复用了订单状态表,并且增加了很多属性,比如说图标等。
1 | // order.js |
转换
key
值为label
就可以这样使用status.find(r => r.key===record.status)
,然后通过.属性名
的方式来使用需要的属性,但是这样也会有一些问题,比如说:
- 条件判断中语义不明,会出现这样的代码,
<a @click='xxx' v-if='record.status === status[1].key'>编辑</a>
,除了我之外其他人并不知道status[1]
是什么意思;- 如果将来 增加/删除 状态的时候会还是需要去同步修改使用下标的组件,不然可能下标错位,当然可以直接追加在最后,但是我有代码洁癖的所以就没办法了。
这个阶段就是我写这篇笔记时的管理,因为项目的 v1.2.x 版本 状态码整体调整了一次,后续状态码一直有小范围的改动,所以出现了需要大面积替换魔术字符串的情况。
那么我就在考虑如何在状态管理的文件中 枚举一次 所有状态,来处理转换状态标签和操作的判断条件,如果后续如果状态码有改动也方便维护的处理方式,就有之后两个阶段的处理方式
阶段三:使用对象来管理
这个阶段有考虑过使用 Map 数据结构 因为可以遍历,但是在取值的时候会比较麻烦,并不能直接使用 链式(变量属性)来使用。
所以使用对象来管理,并且使用 Object.values
来返回所有状态数组,例如以下示例:
1 | // order.js |
这个时候可以通过 getOrderStatus
函数来处理 key-label
的转换,并且可以使用 链式(变量属性)的方式去处理判断条件。
1 | <a @click='xxx' v-if='record.status === status.created.key'>编辑</a> |
那这样就可以很方便的来 转换状态 和 在判断条件中使用,并且不用担心语义化的问题。
但是这边又出现了一个问题,比如说:
在用户下的客户类别中的付费用户,如果单纯使用一个
user.js
来管理,并且使用user.customer.member.key
去判断是否展示操作内容,但是这样的话,在管理端的用户列表中,去替换用户类型的key
为label
就比较麻烦,因为层级会比较深,Object.values
只会返回一层,如果一个一个拿出来手动放到一个数组里边有会显得很呆。
所以!
阶段四:对集中管理文件中的对象拆分
因为如果同一个列别中有多级分类的话,就类似上边的例子,user.customer.member
这种用户类别。所以这个时候就把 user.js
拆分成多个文件,然后再 import
进来,这样既可以在状态判断和label转换的时候引入需要的文件就可以了。
示例:
1 | // customer.js |
1 | // agent.js |
1 | // user.js |
确定是用户类型的时候,只需要 import
对应的 角色.js 的就可以,如果不确定类型的时候就可以使用 user.js
来使用 user.xxx.xxx
来使用对应的角色类型数据,或者用 getAccountType
来获取类型。
现在我是用这种方式来管理状态的,但是我觉得还是有一些问题,准备看一下前人是否已经总结出来这种模式,所以准备把之前买来的设计模式大概翻看一下,看看有没有可用的,也算把自己的基础能力完善起来。
尾声
我在 Segmentfault 上的问题帖:项目中前端部分关于订单状态管理的一些疑问,如果有更好的想法,可以直接评论,或者 📧 Mail给我