uni-app中sku组合逻辑必须由后端返回明确的spec_value_ids字段(如"color:red|size:s")或带key的对象,前端据此生成唯一key并实时重算禁用状态,禁用判断需基于最新选中条件全量过滤sku,避免字符串切分、响应式陷阱及低效遍历。

uni-app里SKU组合逻辑不能靠前端拼字符串推断
后端必须返回明确的 spec_value_ids 字段(如 "color:red|size:s"),而不是只给一个模糊的 spec_str: "红色_S"。靠前端按顺序切分字符串匹配,一旦规格维度增减或顺序调整,整个禁用逻辑就崩了。
常见翻车点:后端返回的 skus 数组里只有 sku_name_arr: ["红", "S"],没带字段名映射。这种结构根本没法做「排除不含当前值的所有 SKU」计算——你连“红”对应的是颜色还是材质都不知道。
- 要求后端在每个 SKU 对象里补全带 key 的标识,例如
{"color": "红", "size": "S"}或标准化字符串"color:red|size:s" - 前端拿到后立刻用
JSON.stringify或哈希函数生成唯一 key,用于快速查找和过滤 - 千万别写
sku.spec_str.split('_')[0] === selectedColor这类脆弱逻辑
点击某个规格值时,禁用其他规格的可用值必须重算
不是“保留已选,筛剩余”,而是每次点击都重新跑一遍完整推理:从所有 SKU 中,先筛选出包含当前已选全部条件的子集,再统计这个子集中每个未选规格出现过的所有值,其余值一律置为 disabled。
比如已选 color:red,当前可选 size 值是 ["S", "M"];再点 size:S,就得重新拿 color:red & size:S 去查,看还剩哪些 material 值存在——中间状态不能缓存,也不能跳步。
-
handleSpecClick里必须清空后续规格:Object.keys(this.selectedSpecs).forEach(name => { if (index > currentIndex) this.$delete(...) - 禁用判断函数
isSpecDisabled(specName, specValue)每次都要基于最新selectedSpecs+ 全量skus实时计算 - 不要用
computed缓存 disabled 状态数组,它依赖响应式链太长,容易滞后;改用watch+ 手动触发更新
uni-app中v-for渲染带disabled状态的规格按钮要绕开响应式陷阱
直接改原始 specs 数组里某个 values 对象的 disabled 字段,v-for 不会更新视图——因为 Vue 无法侦测到对象属性的新增/修改(尤其嵌套深时)。
正确做法是生成一个全新结构:每个规格项都带 values 数组,每个值对象含 name、disabled、selected 等完整字段,并用 key 绑定唯一标识(如 specName + '_' + value)。
- 别写
v-for="v in spec.values" :class="{disabled: v.disabled}"——v.disabled是响应式死区 - 改用
v-for="item in computedSpecList",其中computedSpecList是个完整新数组,每个item.values都是新对象 - 关键:禁用状态变更后,必须触发
this.$forceUpdate()或替换整个computedSpecList引用,否则 UI 不同步
性能敏感点:避免 Array.find 在大量 SKU 下遍历多次
一个商品有 200 个 SKU、5 个规格维度时,每次点击都要对每个未选规格执行一次 skus.filter(...).map(...).includes(...),很容易卡顿。原生 Array.find 在 H5 和小程序里都比 for 循环慢 3–5 倍。
真实场景下,100+ SKU 就得降级:用 for (let i = 0; i 替代链式调用,提前 <code>break,配合 Set 缓存已计算过的组合 key。
- 把全量
skus转成Map<string skuitem></string>,key 为spec_value_ids字符串 - 构建
availableValues时,用for遍历 +if (sku.spec_value_ids.includes(currentKey))判断,比find快且可控 - 节流不是万能的——SKU 选择本身是高频交互,重点在单次计算快,而不是减少触发次数
spec_value_ids 格式不统一,或前端没做字符串标准化(比如空格、大小写、编码差异),导致 includes 匹配失败,禁用逻辑静默失效。










