SKU矩阵本质是规格值间的可达性邻接矩阵,需用计算属性封装生成逻辑与响应式更新,通过矩阵快速剪枝+matchedSku精确匹配实现高性能、高准确的流式交互体验。

计算属性名本身不能“动态构建”矩阵,真正起作用的是用计算属性封装矩阵的生成逻辑和响应式推导过程。关键不是名字怎么写,而是如何把 SKU 的多维规格关系,通过分层数据结构 + 矩阵映射 + 响应式依赖,变成可预测、可调试、不卡顿的流式交互体验。
先明确:SKU 矩阵不是静态二维表,而是规格维度间的可达性图
邻接矩阵在电商中本质是描述“哪些规格值可以共存于一个有效 SKU 中”。比如颜色=红、尺码=L、套餐=套餐2 这三者若共同出现在某个有库存的 SKU 里,就说明它们两两之间(红↔L、L↔套餐2、红↔套餐2)在矩阵中对应位置都应为 1。
所以构建起点不是“写个 matrix: []”,而是:
- 从后端返回的 skuList 中提取所有规格项(如颜色、尺码、套餐)及其全部取值,按组归类并去重
- 为每个规格值分配唯一索引(如 ['红','白','XL','XXL','套餐1','套餐2'] → [0,1,2,3,4,5])
- 初始化全零矩阵,尺寸为 n × n(n 是所有规格值总数)
- 遍历每个有效 SKU(stock > 0 且 skuStatus === 1),将其包含的规格值两两配对,在矩阵对应行列置 1
用计算属性封装矩阵生成与更新逻辑
不要在 data 或 mounted 里一次性算死矩阵。把它声明为 computed,让 Vue 自动追踪 skuList 和库存状态变化:
matrix() {
const values = this.allSpecValues; // 扁平化后的所有规格值数组
const size = values.length;
const mat = Array(size).fill().map(() => Array(size).fill(0));
this.skus.filter(s => s.stock > 0 && s.skuStatus === 1).forEach(sku => {
const indices = sku.skuAttrList.map(attr => values.indexOf(attr.attrValue));
indices.forEach(i => indices.forEach(j => { if (i !== j) mat[i][j] = 1; }));
});
return mat;
}
这样只要 skus 或其内部 stock 字段响应式更新,matrix 就自动重算 —— 不用手动触发,也不用 watch 监听一堆字段。
流式反馈靠“可用值推导”,而非硬编码禁用规则
用户点了一个颜色后,尺码列表该显示哪些?不是查预设规则,而是实时用矩阵回答:“当前已选规格值,在矩阵中能连通的所有同组值有哪些?”
例如:
– 当前 selectedSpecs = { color: '红' }
– color='红' 对应索引 i = 0
– 查 matrix[0] 行中值为 1 的列索引,再反查这些索引属于哪个规格组(比如索引 2、3 属于“尺码”)
– 提取对应 attrValue('XL','XXL'),即为当前可选尺码
这个过程也应封装为 computed:
- availableSizes():基于 selectedSpecs 和 matrix,过滤出当前可选的尺码值
- availablePackages():同理推导套餐选项
- 每个计算属性只关心自己那组规格,彼此解耦,修改一个不影响其他
规避多规格下的矩阵歧义问题
当规格数 ≥3(如颜色+尺码+套餐),单纯两两点连通会引入虚假路径。例如:红↔XL、XL↔套餐2、红↔套餐1 都存在,但“红+XL+套餐1”未必有对应 SKU。
解决方案不是放弃矩阵,而是升级判断粒度:
- 保留矩阵用于快速剪枝(排除明显不可组合的值)
- 最终有效性校验仍回归到 matchedSku 计算属性:遍历 skus 找 specs 完全匹配且 stock > 0 的项
- UI 上,“灰色不可点”由矩阵推导,“加购按钮是否激活”由 matchedSku 决定
这样既保性能(O(n) 矩阵查表),又保准确(O(m) 精确匹配),两者互补不冲突。

















