前端sku最简单的实现方法(2)

该段代码主要处理商品规格选择的逻辑,包括初始化时的状态更新、选中与取消选中的处理,以及判断库存来禁用不可选的规格。同时,在用户选择完所有规格后,将相关信息传递给父组件更新价格等信息。此外,还包含了根据传入的SKUID初始化默认选中的规格功能。
摘要由CSDN通过智能技术生成

上一节拿到了对应的路径字典,现在我们需要根据所选中的进行实施更新状态了

拿到了路径字典我们还需要拿到当前选中的项,来判断搭配他的是否有库存可以进行选择

const clickSpecs = (item, val) => {
      // 如果是禁用状态不作为
      if (val.disabled) return false;
    //如果selected为true的话说明当前项是选中的,再次点击直接取消选中就可以了
 if (val.selected) {
        val.selected = false;
      } else {
      //如果不是的话那么就把当前项目的selected 改为true,其它项改为false
        item.values.forEach((bv) => {
          bv.selected = false;
        });
        val.selected = true;
      }
       //每次选中的时候都要判断一下与此选中项可搭配有库存的
      updateDisabledStatus(props.goods.specs, pathMap);
}

接下来来就是判断他是否再存在与路劲字段内,存在的话咋就可以进行点击选择

  // 首先可以在初始化得时候更新状态是否可以点击(因为有些可能任意规格的都是没有的)
  updateDisabledStatus(props.goods.specs, pathMap);
    // 更新按钮的禁用状态 //这段代码里面可以有点迷,可以自己 debugger 一下
  const updateDisabledStatus = (specs, pathMap) => {
  // 对所有规格进行遍历
  specs.forEach((spec, i) => {
    // 拿到选中的规格集合
    const selectedArr = getSelectedArr(specs);
    // 对规格项内的选项进行遍历
    spec.values.forEach((val) => {
      // 已经选中的按钮不用判断
      if (val.name === selectedArr[i]) return false;
      // 未选中的替换对应的值 (来判断此项搭配是否可以选中,是否存有库存)
      selectedArr[i] = val.name;
      // 过滤无效值得undefined到key
      const key = selectedArr.filter((v) => v).join(spliter);
      // 设置禁用状态
      val.disabled = !pathMap[key];
    });
  });
};
// 得到当前选中规格集合
const getSelectedArr = (specs) => {
  // 先声明一个空数组,用来装入规格
  const selectedArr = [];
  specs.forEach((spec) => {
    // 拿到当前选中项 初始化的时候,第一次进入数组内就是三个undefined
    const selectedVal = spec.values.find((val) => val.selected);
    // 因为后面要转为字符串去路劲字典内寻找,所有顺序不能乱,如果找到的话就添入选中项,如果没有就添入undefined
    selectedArr.push(selectedVal ? selectedVal.name : undefined);
  });
  return selectedArr;
};

此时的话效果就已经实现了,初始化的时候就会调用一下updateDisabledStatus函数,可以直接筛选出没有库存的,变得不可点击,然后每次点击都会调用一下,那么每次点击拿到所有与其搭配的没有库存都会变的不可点击

把选中项数组传给父组件,因为我这要实时更新价格,不同的规格的价格不一样,所有我就在每次点击选项规格的时候加了个判断,如果选中的规格数组的长度,和商品规格数组的长度一样的话,那么就说明所有项都被选中了,就emit给父组件

    const clickSpecs = (item, val) => {
      // 如果是禁用状态不作为
      if (val.disabled) return false;
      // 1. 选中与取消选中逻辑
      if (val.selected) {
        val.selected = false;
      } else {
        item.values.forEach((bv) => {
          bv.selected = false;
        });
        val.selected = true;
      }

      updateDisabledStatus(props.goods.specs, pathMap);
      // 拿到当前选中的数组
      const selectedArr = getSelectedArr(props.goods.specs).filter((v) => v);
      // 判断当前数组的长度和商品规格的长度是否一致
      if (selectedArr.length === props.goods.specs.length) {
        // 如果当前长度一致说明规格选择完整,可以传入父组件做后续操作
        const skuIds = pathMap[selectedArr.join(spliter)];
        // 找多sku的id
        const sku = props.goods.skus.find((sku) => sku.id === skuIds[0]);
        // 传值
        console.log("111");
        emit("change", {
          skuId: sku.id,
          price: sku.price,
          oldPrice: sku.oldPrice,
          inventory: sku.inventory,
          specsText: sku.specs
            .reduce((p, n) => `${p} ${n.name}:${n.valueName}`, "")
            .replace(" ", ""),
        });
      } else {
        emit("change", {});
      }
    };

如果你还有其它需求,例如点进来默认选中那个规格,那么就可以加一段这个代码

  // 初始化选中
    if (props.SkuId) {
      initSelectedStatus(props.goods, props.SkuId);
    }
// 根据传入的skuid做默认选中
const initSelectedStatus = (goods, SkuId) => {
  // 先找到id对应的sku
  const sku = goods.skus.find((sku) => sku.id === SkuId);
  // 遍历规格列表,因为规格里有selected是来控制是否选中的
  goods.specs.forEach((item, i) => {
    const val = item.values.find((val) => val.name == sku.specs[i].valueName);
    val.selected = true;
  });
};

这段代码没有什么大问题,但是还是有点细节需要磨一下的,因为当时我没有用这个功能,也就没有细磨,例如如果传进来的sku是没有库存的,那么你就需要在点击提交订单,或者加入购物车的时候做一些判断

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值