SKU(stock keeping unit庫存量單位)組合查詢是網上商場一個非常常用的功能。具體來說,一件商品會有許多型號,許多顏色,許多產地,許多碼寸,而滿足用戶選中的這些條件的具體商品可能有庫存,也可能沒有。我們把型號,顏色,產地,碼寸什么的都分成一欄,每一欄的選項都有三種形態,可選,不可選,已選中。選中某一欄的一個選項的話,會影響到另外一些欄的項目的選中狀態。如下圖:
網上也有文章介紹它們的實現,涉及大量復雜的算法,HTML都是用JS動態生成的,非常不直觀。並且那個東西這么簡單,還要用那么復雜的算法啊,腦子被狗吃了。
在avalon中,由於VM對象是一個狀態機,對這種聯動功能有着天然的優勢。我們只要把數據列出來,剩下的事就交給avalon好了。
下面是模板,它是由GITHUB的一個例子改過來的。一共五欄,換言之,VM有五個數組。然后里面每頂通過ms-class處理它們的狀態。選擇是通過點擊事件實現,因此有ms-click。每個項目是否選中,通過漲是否等於某一個值判定,因此我搞了versionsChecked,colorsChecked,comboChecked等變量。
<div ms-controller="sku" id="sku">
<div>
版本:
<span ms-each-el="versions">
<span class="cell" ms-click="select(el, 'versions')" ms-class-disabled='el.disabled' ms-class-checked='versionsChecked == el.value'>{{el.text}}</span>
</span>
</div>
<div>
機身顏色:
<span ms-each-el="colors">
<span class="cell" ms-click="select(el, 'colors')" ms-class-disabled='el.disabled' ms-class-checked='colorsChecked == el.value'>{{el.text}}</span>
</span>
</div>
<div>
手機套餐:
<span ms-each-el="combo">
<span class="cell" ms-click="select(el, 'combo')" ms-class-disabled='el.disabled' ms-class-checked='comboChecked == el.value'>{{el.text}}</span>
</span>
</div>
<div>
機身內存:
<span ms-each-el="memory">
<span class="cell" ms-click="select(el, 'memory')" ms-class-disabled='el.disabled' ms-class-checked='memoryChecked == el.value'>{{el.text}}</span>
</span>
</div>
</div>
sku最麻煩之處在於,點擊了某一欄的項目會影響到其他欄的項目,這種邏輯我抽象成一個command命令,以columnName:item1,item2...;columnName2:item3,item4...;保存。
具體如下:
var model = avalon.define("sku", function(vm) {
vm.select = function(el, name) {
if (el.disabled)
return
var command = el.command
model[name + "Checked"] = el.value
command.split(";").forEach(function(str) {
var arr = str.split(":")
var check = arr[1]
var array = model[arr[0]] || []
array.forEach(function(elem) {
elem.disabled = !!(check && check.indexOf(elem.value) !== -1)
})
})
}
vm.versions = [
{value: 'cn', "text": "中國大陸", disabled: false, command: "colors:lightgreen;"},
{value: "hk", text: "港澳台", checked: false, command: "colors:lightyellow,black,blue,gray,yellow,white"},
{value: "eu", text: "歐洲", checked: false, command: "colors:lightyellow,blue,gray,yellow,red,lightgreen"}
]
vm.versionsChecked = ""
vm.colors = [
{value: 'lightyellow', "text": "淺黃色", disabled: false, command: "versions:hk,eu"},
{value: "black", text: "黑色", disabled: false, command: "versions:hk"},
{value: "blue", text: "藍色", disabled: false, command: "versions:hk,eu"},
{value: "gray", text: "淺灰色", disabled: false, command: "versions:hk,eu"},
{value: "yellow", text: "黃色", disabled: false, command: "versions:hk,eu"},
{value: "white", text: "白色", disabled: false, command: "versions:hk"},
{value: "lightgreen", text: "淺綠色", disabled: false, command: "versions:cn,eu;combo:set2,set3"},
{value: "red", text: "紅色", disabled: false, command: "versions:eu"}
]
vm.colorsChecked = ""
vm.combo = [
{value: 'standard', "text": "官方標配", disabled: false,command: ""},
{value: "set2", text: "套餐二", disabled: false,command: "colors:lightgreen"},
{value: "set3", text: "套餐三", disabled: false,command: ""}
]
vm.comboChecked = ""
vm.memory = [{value: "32g", text: "32G", disabled: false,command: ""}]
vm.memoryChecked = "32g"
})
再加一點CSS裝飾一下就搞定。
#sku .cell{
display:inline-block;
padding:2px 5px;
border:2px solid #ccc;
color:#000;
cursor:pointer;
height: 18px;
line-height: 18px;
}
#sku .cell.checked{
border-color:red!important;
color:red!important;
}
#sku .cell.disabled{
border:2px dashed #d6d6d6;
color:#cdcdcd;
cursor:not-allowed;
}
#sku div{
margin-top:10px;
}
大家可以到我的GITHUB,下載回來運行
