先一步步剖析需求!
场景如图:
这样看来需求如下:
页面上输入金额,并显示到右下角。
然后打开抽屉,抽屉里面显示可用金额和已用金额,可用金额默认等于总金额。
然后抽屉里面输入金额的时候,可用金额减少,已用金额增加。
所以一开始是这样设计的:
1、在dva的model里面定义了三个金额字段,分别为 totalAmount、availableAmount、usedAmount
2、在第一个输入金额的框那里,直接通过dispatch保存最新的值进去。大概是这样
dispatch({ type: 'xxx/save', payload: { totalAmount: '输入框的值' } })
3、将totalAmount显示到页面上
4、打开抽屉,初始化时,availableAmount = totalAmount; usedAmount = 0;
5、填写第二个金额输入框,同理直接使用dispatch更新
dispatch({ type: 'xxx/save', payload: { availableAmount: totalAmount - '输入框的值', usedAmount: '输入框的值' } })
6、将这个两个金额显示到页面上。
至此就实现了上诉效果。然而,事情可能并没有那么简单........
新需求如图:
需求加了两个Icon,一个新增,一个删除。
意思就是Input框是批量的,那就是说,会有无数个地方更新金额,并且我不能直接使用「输入的值」,而是需要先进行汇总计算。
所以,这个时候我把这两个dispatch的逻辑分别提了两个公共的方法出来。放在了它们所在的组件当中。
方法大概是这样
const setTotalAmount = (amount) => { dispatch({ type: 'xxx/save', payload: { totalAmount: '新的值' } }) } /** * * @param {number} amount 抽屉里面所有输入框值的求和 */ const setAvailableAmountAndUsedAmount = (amount) => { dispatch({ type: 'xxx/save', payload: { availableAmount: totalAmount - amount, usedAmount: amount } }) }
end~
功能实现了,但是有些问题:
- 金额字段在model里面,更新值的方法在对应的两个组件中,代码逻辑不清晰,不方便阅读和管理。
- 不可重用,后期如果有同样的场景,需要再写一遍。
果然。事情就这样过了几个月,另外一个模块出现的同样的需求场景。
我开始思考这个问题,那么我还得按照同样的方式,再在model中定义三个amount字段,然后再写两个方法来更新它???
如果我不写写一套一样的,用同一套model和字段,那么数据在流转的过程中,是不是就混淆在一起了呢?
如果把它抽象成一个类Amount
它的状态是:总金额、可用金额、已用金额。
它的行为是:更新总金额、更新可用和已用金额。
那现在开始编class Amount // 总金额 totalAmount = 0;
class Amount { // 总金额 totalAmount = 0; // 可用金额 availableAmount = 0; // 已用金额 usedAmount = 0; constructor(defaultAmount) { // 当页面回显的时候,可以直接通过默认值来初始化 this.totalAmount = defaultAmount ?? 0; } /** * @param {number} amount 总金额 */ setTotalAmount(amount) { this.totalAmount = amount; this.availableAmount = amount; } /** * @param {number} amount 已使用金额 */ setAvailableAndUsedAmount(amount) { this.availableAmount = this.totalAmount - amount; this.usedAmount = amount; } getTotalAmount() { return this.totalAmount; } getAvailableAmount() { return this.availableAmount; } getUsedAmount() { return this.usedAmount; } }
好处:
- 金额的计算和显示功能,统一管理,逻辑清晰
- 代码重用,每次只需要 new 一个对象