sku选择解决方案

1,352 阅读3分钟

介绍

一个看似简单的sku里面的水也是蛮深的,被同一个问题烦恼你三次的时候就要想解决方案,在web端还是移动端都会遇到,所以就有了下面的sku选择解决方案 思路来源:hooray.github.io/posts/8b2bd… 当我看到这篇文章当中的所有规格列出来的列表的时候就有了一些想法

目标

  • 传入当前选中的规格来确定各个规格是否可选中
  • 传入当前选中的规格确定当前选中的具体哪一个sku

思路

通过sku列表即可得到所有的用户能选中的状态的集合,这样提前把这些集合给得到(不可否认的是这个集合在规格多的时候会很大,在这里空间和时间我选择时间),当用户选择规格时,直接去map前面得到的集合(这里的时间成本理论上就跟从对象里取一个key一样的成本),就可以得到sku所有的可能性,也就得到了当前哪些规格可以选中与否

实现

商品的数据:sku列表和规格列表

const skuListData = [
  { specIds: ["100", "010"], stock: 12, price: 1, img: "1" },
  { specIds: ["100", "020"], stock: 12, price: 1, img: "1" },
  { specIds: ["200", "020"], stock: 12, price: 1, img: "1" },
];

const specListData = [
  {
    name: "等级",
    items: [
      { name: "一级", id: "100" },
      { name: "二级", id: "200" },
    ],
  },
  {
    name: "品牌",
    items: [
      { name: "农夫山泉", id: "010" },
      { name: "潘苹果", id: "020" },
    ],
  },
];

如何得到所有的用户能选中的状态的集合

通过下面的两个函数得到

function arrayCombine(targetArr: any) {
  var resultArr = [];
  for (var n = 0; n <= targetArr.length; n++) {
    var flagArrs = getFlagArrs(targetArr.length, n);
    while (flagArrs.length) {
      var flagArr = flagArrs.shift() || [];
      //   var combArr = Array(targetArr.length);
      var combArr = [];
      for (var i = 0; i < targetArr.length; i++) {
        if (flagArr[i]) {
          combArr.push(targetArr[i]);
        }
      }
      resultArr.push(combArr);
    }
  }
  return resultArr;
}
// 从m中取n的所有组合
function getFlagArrs(m: any, n: any) {
  var flagArrs = [],
    flagArr = [],
    isEnd = false;
  for (var i = 0; i < m; i++) {
    flagArr[i] = i < n ? 1 : 0;
  }
  flagArrs.push(flagArr.concat());
  // 当n不等于0并且m大于n的时候进入
  if (n && m > n) {
    while (!isEnd) {
      var leftCnt = 0;
      for (var i = 0; i < m - 1; i++) {
        if (flagArr[i] === 1 && flagArr[i + 1] === 0) {
          for (var j = 0; j < i; j++) {
            flagArr[j] = j < leftCnt ? 1 : 0;
          }
          flagArr[i] = 0;
          flagArr[i + 1] = 1;
          var aTmp = flagArr.concat();
          flagArrs.push(aTmp);
          if (aTmp.slice(-n).join("").indexOf("0") == -1) {
            isEnd = true;
          }
          break;
        }
        flagArr[i] == 1 && leftCnt++;
      }
    }
  }
  return flagArrs;
}

传入sku列表的规格组合到arrayCombine的结果

解释:比如我的第一个sku数据的 specIds: ["100", "010"] 这个sku就是由100,010两个规格id组合起来的,那么他在选择这个sku的过程中所有的情况就是上面arrayCombine的结果的第一条,分别为不选,选择100规格,选择010规格,选择100规格和010规格四个情况

所以再把上面的规格组合去个重,就得到了用户选择规格所有的情况,当用户选择规格的时候,就可以直接提前知道他当前可选那些sku,以此来得到当前那些规格可选与否

结尾

上面的思路讲的就是核心的思路,具体的实现,比如我知道那些sku可选怎么判断规格可选呢就没有具体再展开讲了,如果有兴趣继续看下去移步:github.com/winljm001/s…

可以直接引入作者写的库 sku-status-class 用上面的数据试试(实际使用的数据字段不一样再使用的时候自己map一次就行了)

功能上是没有问题的,经过思考也有可以优化的点,后面有bug或者空了再继续迭代优化

使用方法:

import Sku from "sku-status-class";
const selected = ["100", "010"];
const a = new Sku(skuListData, specListData);
// 获取规格状态
console.log(a.getSpecListStatus(selected));
// 获取选中的规格
const a = new Sku(skuListData, specListData);
// console.log(a.getSkuGoods(selected));

上面的使用结果就会得到

有了specStatus你就可以在页面上渲染当前规格的状态为:选中、可选、不可选