vue实现sku选择
Vue 实现 SKU 选择
SKU(Stock Keeping Unit)选择是电商系统中常见的功能,允许用户通过组合不同属性(如颜色、尺寸)来选择商品。以下是基于 Vue 的实现方法。
数据结构设计
SKU 数据通常包含属性列表和 SKU 列表。属性列表描述商品的维度(如颜色、尺寸),SKU 列表包含具体组合及其库存、价格等信息。
data() {
return {
attributes: [
{ name: '颜色', values: ['红色', '蓝色', '绿色'] },
{ name: '尺寸', values: ['S', 'M', 'L'] }
],
skus: [
{ id: 1, color: '红色', size: 'S', stock: 10, price: 100 },
{ id: 2, color: '红色', size: 'M', stock: 5, price: 120 },
// 其他 SKU...
],
selected: {} // 存储用户选择的属性值
}
}
属性选择交互
为每个属性创建选择按钮,用户点击时更新 selected 对象。
<div v-for="attr in attributes" :key="attr.name">
<h3>{{ attr.name }}</h3>
<button
v-for="value in attr.values"
:key="value"
@click="selectAttr(attr.name, value)"
:class="{ active: selected[attr.name] === value }"
>
{{ value }}
</button>
</div>
methods: {
selectAttr(attrName, value) {
this.$set(this.selected, attrName, value)
this.checkAvailability()
}
}
SKU 可用性检查
根据当前选择的属性组合,检查哪些 SKU 可用并更新 UI。
methods: {
checkAvailability() {
const selectedAttrs = Object.values(this.selected)
if (selectedAttrs.length === this.attributes.length) {
// 完整选择时查找匹配的 SKU
const matchedSku = this.skus.find(sku =>
this.attributes.every(attr =>
sku[attr.name.toLowerCase()] === this.selected[attr.name]
)
)
// 处理匹配结果...
}
}
}
禁用不可选选项
当某些属性组合无库存时,应禁用对应选项。
computed: {
disabledValues() {
const disabled = {}
this.attributes.forEach(attr => {
disabled[attr.name] = attr.values.filter(value => {
const tempSelected = { ...this.selected, [attr.name]: value }
return !this.hasStockForCombination(tempSelected)
})
})
return disabled
}
}
完整示例
<template>
<div>
<div v-for="attr in attributes" :key="attr.name">
<h3>{{ attr.name }}</h3>
<button
v-for="value in attr.values"
:key="value"
@click="selectAttr(attr.name, value)"
:class="{
active: selected[attr.name] === value,
disabled: disabledValues[attr.name]?.includes(value)
}"
:disabled="disabledValues[attr.name]?.includes(value)"
>
{{ value }}
</button>
</div>
<div v-if="currentSku">
<p>价格: {{ currentSku.price }}</p>
<p>库存: {{ currentSku.stock }}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
attributes: [
{ name: '颜色', values: ['红色', '蓝色', '绿色'] },
{ name: '尺寸', values: ['S', 'M', 'L'] }
],
skus: [
{ id: 1, color: '红色', size: 'S', stock: 10, price: 100 },
{ id: 2, color: '红色', size: 'M', stock: 5, price: 120 },
// 其他 SKU...
],
selected: {},
currentSku: null
}
},
computed: {
disabledValues() {
const disabled = {}
this.attributes.forEach(attr => {
disabled[attr.name] = attr.values.filter(value => {
const tempSelected = { ...this.selected, [attr.name]: value }
return !this.hasStockForCombination(tempSelected)
})
})
return disabled
}
},
methods: {
selectAttr(attrName, value) {
this.$set(this.selected, attrName, value)
this.checkAvailability()
},
checkAvailability() {
const selectedCount = Object.keys(this.selected).length
if (selectedCount === this.attributes.length) {
this.currentSku = this.skus.find(sku =>
this.attributes.every(attr =>
sku[attr.name.toLowerCase()] === this.selected[attr.name]
)
)
} else {
this.currentSku = null
}
},
hasStockForCombination(tempSelected) {
return this.skus.some(sku =>
this.attributes.every(attr =>
sku[attr.name.toLowerCase()] === tempSelected[attr.name]
)
)
}
}
}
</script>
<style>
.active {
background-color: #42b983;
color: white;
}
.disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>
性能优化建议
对于大型 SKU 列表,可以考虑以下优化:
- 使用 Map 或 Object 建立 SKU 的快速查找表
- 对不可用选项进行缓存
- 使用虚拟滚动处理大量属性值的情况
复杂场景处理
当属性之间存在依赖关系时(如某些颜色没有某些尺寸),需要额外处理:
methods: {
filterAvailableValues(attrName) {
if (!this.selected[attrName]) return this.attributes.find(a => a.name === attrName).values
return this.attributes.find(a => a.name === attrName).values.filter(value => {
const tempSelected = { ...this.selected, [attrName]: value }
return this.hasStockForCombination(tempSelected)
})
}
}
以上实现提供了基本的 SKU 选择功能,可根据实际需求进行调整和扩展。







