电商经典的sku选择v2优化版
迭代
最近公司又要做新的业务需求,所以sku选择重新写一次,比起之前的做法,更加简洁、逻辑更清晰。(以前的sku选择旧文章直接从博客中删除了,当前文章即为最优版本)
业务说明
电商业务中,商品的规格选择是最常见的操作,如果规格比较少,完全可以使用扁平化的一维数组
完全展示,例如红色+128G+6G内存
;
但我们平台的部分商品,规格非常多,可能交叉握手后达到几十上百种,这时候就不能展示组合后的选择,因为太多了,用户直接看花眼;
这种情况,只能是下图中类似于淘宝的规格选择,每次交互操作,能选择的进行点亮,没有库存的(比如任何包含丝绸
材质的)直接置灰禁用;
部分规格,比如红色 大 纯棉
是没有库存的,但是红色 小 纯棉
,红色 中 纯棉
又有库存,这种情况,在选择部分规格后,最终还未选择的规格,也要置灰处理,如图操作;
交互由前端全部完成;
以下为了能清晰解释和说明,我将数据和页面单独提出来,做了一个简单的DEMO来演示,DEMO源码也放在了github上,具体的实现过程可以直接看源码:github源码地址
方法思路
数据结构
先看一下服务端返回的原始数据结构:
properties
:规格的属性,比如颜色(红黄蓝绿)
、尺寸(小中大)
、型号(abcd)
,只包含了基础的规格类目信息,前端的布局也使用properties
数组进行渲染;
其中attr_id
是规格的属性id,即颜色
这个类目的id,attribute_id
是规格的具体属性值id,即红色
这个属性值的id;
skuData
:服务端将所有子规格交叉组合给出的枚举,比如:红色,小,a
,并且每种组合都明确给出了库存数量;
可以看到,skuData
中的properties
,是properties
中的attr_id
和attribute_id
的组合,比如颜色
的attr_id
是2000532
,红色
的attribute_id
是2006533
,那么properties
就是2000532:2006533
;
stock
是库存数量,如果为0的话,肯定就是无库存,要进行置灰禁用;
重点:什么叫有效规格?什么时候该置灰禁用?
重点部分来了,这部分是整个sku选择的核心,也是最难的部分,如果理解了这个,那么整个sku选择就很简单了;
先来理解清楚概念,后续再讲代码逻辑;
先看初始化的情况,为什么丝绸
这一项,一开始就置灰了?可以看skuData
的数据,凡是包含丝绸
这一项的规格,库存都是0
,所以一开始,认为丝绸
就是无效的,要被禁用;
反之,某一个规格项,只要在skuData
至少有一项包含它,并且库存大于0,那么就是有效的规格;
例如:点击选了了部分规格,例如红色;小
,那么只要红色;小
是skuData
中properties
的子集
,并且库存大于0,就是有效规格;
规格项点击时的交互
当用户点击某些规格项时,某些规格也会被禁用,例如:我选择了红色;中
时,绿色
、大
、丝绸
3个规格项是被禁用的,为什么操作过程中,某些项就被禁用了?
因为每操作一步,都会有已被选择项
,我们需要将已被选择项
套用到每一个规格上,组成一个预检查规格值
,在skuData
中,校验该值是否有效,例如:
左边的图,就是组合后的预检查规格值
,红色
-> 红色;红色;中
;黄色
-> 黄色;红色;中
… …但这样组合,肯定存在一些问题,某些同一类的规格重复了
过滤后,正确的检查项应该是右图:红色
-> 红色;中
;黄色
-> 黄色;中
也就说,绿色;中
,红色;大
,红色;中;丝绸
,这3种情况,在skuData
中,只要是包含它们的,都没有库存了,所以要被置灰
思路总结
每次计算时,先取得已被选择项
,然后遍历properties
,将已被选择项
套用到每一个规格上,组成预检查规格值
,在skuData
中,校验该值是否有效,如果无效,就将该规格项置灰禁用;
代码具体实现
properties初始化处理
1 |
|
重点在于selectedSku
,这个对象,是用来存储已被选择项
的,每次操作时,都会更新这个对象;selectedSku
内的value
值,就是每个小规格的com_id
(即 父级attr_id
拼接 自身的attribute_id
)
skuData初始化处理
1 |
|
仅仅将properties
处理为数组形式,方便后续的处理;
规格计算
1 |
|
以上的代码都非常好理解,遍历properties
,如果为无效,那么就将disabled
置为1
,重点在于isEffectSku
这个方法
isEffectSku方法
1 |
|
每一次规格点击时
1 |
|
每次规格点击时,如果点击的规格无效,直接return不作任何处理;如果有效,仅做点亮和取消点亮的操作,最后重新执行计算;
最后
规格选择看似很复杂,但只要理解清楚原理,理清思路,整体实现还是非常简单的,希望这篇文章能帮助到你;
DEMO源码也放在了github上,具体的实现过程可以下载下来直接看代码:github源码地址