目前有一個這樣的需求 類似淘寶 京東選擇?
但是在人家大廠給的數據我不清除是什么樣子的?
我這邊后端給的數據 一開始是想把規格全部顯示出來的 發現實現不了 后端的數據有限
因為必須選擇一個顏色 才可以對應的第二個規格 才知道有沒有庫存
因為這個庫存 是由兩個規格決定的 這種的話 要想 做成京東或者淘寶那種?
無庫存無法顯示的效果是不行的 看一下我的后端給的數據
?
[{"id": "1384947912936914944","image": "","stock": 0,"supplyCode": "","sellerPrice": "8250","masterAttrName": "顏色","masterAttrValue": "紫綠色調00374","slaveAttrName": "參考身高","slaveAttrValue": "160cm"},{"id": "1384947912953692160","image": "","stock": 19,"supplyCode": "","sellerPrice": "8250","masterAttrName": "顏色","masterAttrValue": "紫綠色調00374","slaveAttrName": "參考身高","slaveAttrValue": "165cm"},{"id": "1384947912970469376","image": "","stock": 50,"supplyCode": "","sellerPrice": "8250","masterAttrName": "顏色","masterAttrValue": "紅綠色調00364","slaveAttrName": "參考身高","slaveAttrValue": "160cm"},{"id": "1384947912987246592","image": "","stock": 100,"supplyCode": "","sellerPrice": "8250","masterAttrName": "顏色","masterAttrValue": "紅綠色調00364","slaveAttrName": "參考身高","slaveAttrValue": "165cm"}
]
這里面的數據 stock 是 0 的話 我前端自己又加了一個數據 isDisable字段 為true 無法選擇
需要把這個數據整體更換成 這樣的就好了
[{"value": "紫綠色調00374","disabled": false,"heights": [{"value": "160cm","stock": 0,"disabled": true},{"value": "165cm","stock": 19,"disabled": false}]},{"value": "紅綠色調00364","disabled": false,"heights": [{"value": "160cm","stock": 50,"disabled": false},{"value": "165cm","stock": 100,"disabled": false}]}
]
最終我們需要這樣的數據來顯示 就好了
我認為這樣的數據 才是 最符合 的 很明顯 后端給的數據 差距太大 說實話?
我一下子沒有想起來怎么把上面的數據處理成下面這樣
我也是搜了搜
使用 new Map? 映射一下 最后在Array.from(new Map.values)? 映射出來就好了
我直接上代碼吧
colorOptions: [],heightOptions: [],filterOptions: [], 中轉 相當于選擇了規格1 的經過 去篩選規格2 的顯示selectedColor: null, //規格1選擇的結果selectedHeight: null //規格1選擇的結果initOptions() {const colorMap = new Map();const heightMap = new Map();// 首先收集所有顏色和身高選項this.originalData.forEach(product => {// 處理顏色選項if (!colorMap.has(product.masterAttrValue)) {colorMap.set(product.masterAttrValue, {value: product.masterAttrValue,disabled: false, // 初始不禁用heights: new Map() // 存儲身高和對應的庫存});}const colorOption = colorMap.get(product.masterAttrValue);colorOption.heights.set(product.slaveAttrValue, product.stock);// 處理身高選項if (!heightMap.has(product.slaveAttrValue)) {heightMap.set(product.slaveAttrValue, {value: product.slaveAttrValue,disabled: product.stock === 0, // 身高選項的禁用狀態基于庫存colors: new Map() // 存儲顏色和對應的庫存});}const heightOption = heightMap.get(product.slaveAttrValue);heightOption.colors.set(product.masterAttrValue, product.stock);});// 轉換顏色選項:只有當所有身高都缺貨時才禁用顏色this.colorOptions = Array.from(colorMap.values()).map(color => {const hasStock = Array.from(color.heights.values()).some(stock => stock > 0);return {...color,disabled: !hasStock,heights: Array.from(color.heights.entries()).map(([height, stock]) => ({value: height,stock,disabled: stock === 0}))};});// 轉換身高選項this.heightOptions = Array.from(heightMap.values()).map(height => ({...height,colors: Array.from(height.colors.entries()).map(([color, stock]) => ({value: color,stock,disabled: stock === 0}))}));console.log(this.colorOptions, 'this.colorOptions');console.log(this.heightOptions, 'this.colorOptions');},
上面的數據到下面 這個方法就夠了
然后頁面上顯示我也拿出來
<div class="cate-selected-box"><div class="cate-title"> {{ info.masterAttrName }}</div><ul class="cate-list"><li class="level1-item" v-for="color in colorOptions" :key="color.value" @click="selectColor(color)":class="{ 'disabled': color.disabled, 'selected': selectedColor === color.value }">{{ color.value }}<span v-if="color.disabled">(缺貨)</span></li></ul><div class="cate-title"> {{ info.slaveAttrName }}</div><ul class="cate-list" v-if="filterOptions.length"><li class="level1-item" v-for="item in filterOptions" v-if="item.value != '-'" :key="item.value"@click.stop="selectHeight(item)":class="{ 'disabled': item.disabled, 'selected': selectedHeight === item.value }">{{ item.value }}<span v-if="item.disabled">(缺貨)</span></li></ul><div class="selected-info" v-if="info.productSpecials && info.productSpecials.length > 1"><div class="item"><div class="label">已選擇:</div><!-- && --><div class="value"v-if="(info.slaveAttrValues && info.slaveAttrValues.length) && (info.masterAttrValues && info.masterAttrValues.length)"><div v-if="selectedColor && selectedHeight">{{ selectedColor }} - {{ selectedHeight }}</div></div><div class="value"v-if="(!info.slaveAttrValues) && (info.masterAttrValues && info.masterAttrValues.length)"><div v-if="selectedColor">{{ selectedColor }}</div></div></div></div></div>
li {list-style: none;padding: 0;margin: 0;
}ul {padding: 0;margin: 0;
}.cate-selected-box {.cate-title {font-weight: 700;margin: 10px 0;}.selected-info {margin: 15px;margin-top: 25px;.item {display: flex;align-items: center;.label {color: 858a99;}.value {color: #6034b9;margin-left: 10px;}}}.cate-list {cursor: pointer;display: flex;flex-wrap: wrap;align-items: center;.level1-item {padding: 10px 20px;border: 1px solid #f7f8f9;border-radius: 5px;transition: all 0.3s;margin: 6px;}.level1-item:hover {border: 1px solid #6034b9;}.level1-item:nth-child(n+2) {// margin-left: 10px;// margin: 10px;}}}.disabled {color: #ccc;cursor: not-allowed;
}.selected {background-color: #6034b9;color: white;border-color: #6034b9;
}
這一部分的樣式我也顯示出來了
大家如果把這個放到vue 文件中 是直接能夠顯示效果的
這里面的難點其實是這個 new Map 的使用 我也使用的好少 Es6 的方法如果說不使用 這個 其實 也能夠想辦法 把這個處理好 但是方法不太好想
這些都是經驗嗎 每次記一點 下次遇到了就能有想法了
學習前端就是這樣 哪怕你死記硬背 有時候 也有用 就會知道什么方法處理什么問題