You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实现类似拼多多的SKU商品选择功能

拼多多式SKU选择功能实现方案

基于你提供的SKU数据结构,要实现点击属性选项后自动展示可搭配的其他属性选项,核心是根据已选属性集合,过滤出所有存在对应有效SKU的属性值,以下是具体实现步骤:

1. 数据预处理(提前整理,提升查询效率)

先把原始SKU数据转换成更易查询的结构,方便后续快速筛选有效组合:

const skus = [/* 你的SKU数组数据 */];

// 存储所有有效属性组合:key为属性组合字符串,value为对应SKU信息
const validCombinations = {};
// 按属性名分组的所有属性值集合
const attributeValues = {};

skus.forEach(sku => {
  const attrObj = {};
  const attrKeyParts = [];
  
  sku.attributes.forEach(attr => {
    attrObj[attr.attr_name] = attr.value_name;
    attrKeyParts.push(`${attr.attr_name}:${attr.value_name}`);
    
    // 填充属性值分组
    if (!attributeValues[attr.attr_name]) {
      attributeValues[attr.attr_name] = new Set();
    }
    attributeValues[attr.attr_name].add(attr.value_name);
  });
  
  // 生成唯一的组合键(排序后避免顺序问题)
  const comboKey = attrKeyParts.sort().join(',');
  validCombinations[comboKey] = {
    skuId: sku.id,
    price: sku.price,
    stock: sku.stock
  };
});

// 将Set转为数组,方便后续操作
Object.keys(attributeValues).forEach(key => {
  attributeValues[key] = Array.from(attributeValues[key]);
});

2. 维护已选属性状态

用一个对象记录用户当前已选的属性,初始为空:

// 示例:选中红色后变为 { color: "red" }
const selectedAttributes = {};

3. 属性选项点击逻辑

处理用户点击属性值的交互,更新已选状态并触发可选值计算:

function handleAttributeClick(attrName, valueName) {
  // 切换选中/取消选中状态
  if (selectedAttributes[attrName] === valueName) {
    delete selectedAttributes[attrName];
  } else {
    selectedAttributes[attrName] = valueName;
  }
  
  // 计算并更新所有属性的可选状态
  updateAvailableAttributes();
}

4. 核心:计算可选属性值

根据已选属性,筛选出所有能组合出有效SKU的属性值:

function updateAvailableAttributes() {
  // 先筛选出包含已选属性的所有有效组合
  let filteredCombos = Object.keys(validCombinations);
  
  // 按已选属性过滤组合
  Object.entries(selectedAttributes).forEach(([attrName, value]) => {
    filteredCombos = filteredCombos.filter(combo => combo.includes(`${attrName}:${value}`));
  });

  // 初始化所有属性值为不可选
  const availableAttrs = {};
  Object.keys(attributeValues).forEach(attrName => {
    availableAttrs[attrName] = {};
    attributeValues[attrName].forEach(value => {
      availableAttrs[attrName][value] = false;
    });
    // 已选中的属性值默认可选
    if (selectedAttributes[attrName]) {
      availableAttrs[attrName][selectedAttributes[attrName]] = true;
    }
  });

  // 遍历筛选后的组合,标记可选的属性值
  filteredCombos.forEach(combo => {
    const attrs = combo.split(',').map(item => {
      const [name, val] = item.split(':');
      return { name, val };
    });
    attrs.forEach(({ name, val }) => {
      // 未选中的属性,标记其出现的值为可选
      if (!selectedAttributes[name]) {
        availableAttrs[name][val] = true;
      }
    });
  });

  // 更新UI状态
  renderAttributeOptions(availableAttrs);
}

5. UI层更新

根据计算出的可选状态,更新每个属性选项的样式和可交互性:

function renderAttributeOptions(availableAttrs) {
  document.querySelectorAll('.attr-option').forEach(btn => {
    const attrName = btn.dataset.attr;
    const valueName = btn.dataset.value;
    const isAvailable = availableAttrs[attrName][valueName];
    const isSelected = selectedAttributes[attrName] === valueName;

    // 更新样式与禁用状态
    btn.classList.toggle('selected', isSelected);
    btn.classList.toggle('disabled', !isAvailable && !isSelected);
    btn.disabled = !isAvailable && !isSelected;
  });

  // 若所有属性都已选中,展示对应SKU的价格、库存
  if (Object.keys(selectedAttributes).length === Object.keys(attributeValues).length) {
    const comboKey = Object.entries(selectedAttributes)
      .map(([name, val]) => `${name}:${val}`)
      .sort()
      .join(',');
    const skuInfo = validCombinations[comboKey];
    if (skuInfo) {
      document.getElementById('sku-price').textContent = skuInfo.price;
      document.getElementById('sku-stock').textContent = skuInfo.stock;
    }
  }
}

6. 边界情况处理

  • 取消所有选中时,调用updateAvailableAttributes会自动恢复所有选项为可选
  • 库存为0的SKU,可在预处理阶段从validCombinations中排除,或标记为不可选
  • 若筛选后无有效组合,可提示用户调整已选属性

内容的提问来源于stack exchange,提问作者oren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:10:58