所說起的購物數量的加減,如今說說商品屬性值聯動選擇。小程序
爲了讓同窗們有個直觀的瞭解,到電商網截了一個圖片,就是紅圈所示的部分數組
如今就爲你們介紹這個小組件,在小程序中,該如何去寫網絡
下圖爲本項目的圖:數據結構
wxml:xss
1 <view class="title">商品屬性值聯動選擇</view> 2 <!--options--> 3 <view class="commodity_attr_list"> 4 <!--每組屬性--> 5 <view class="attr_box" wx:for="{{attrValueList}}" wx:for-item="attrValueObj" wx:for-index="attrIndex"> 6 <!--屬性名--> 7 <view class="attr_name">{{attrValueObj.attrKey}}</view> 8 <!--屬性值--> 9 <view class="attr_value_box"> 10 <!--每一個屬性值--> 11 <view class="attr_value {{attrIndex==firstIndex || attrValueObj.attrValueStatus[valueIndex]?(value==attrValueObj.selectedValue?'attr_value_active':''):'attr_value_disabled'}}" bindtap="selectAttrValue" data-status="{{attrValueObj.attrValueStatus[valueIndex]}}" 12 data-value="{{value}}" data-key="{{attrValueObj.attrKey}}" data-index="{{attrIndex}}" data-selectedvalue="{{attrValueObj.selectedValue}}" wx:for="{{attrValueObj.attrValues}}" wx:for-item="value" wx:for-index="valueIndex">{{value}}</view> 13 </view> 14 </view> 15 </view> 16 <!--button--> 17 <view class="weui-btn-area"> 18 <button class="weui-btn" type="primary" bindtap="submit">肯定</button> 19 </view>
wxss:ui
1 .title { 2 padding: 10rpx 20rpx; 3 margin: 10rpx 0; 4 border-left: 4rpx solid #ccc; 5 } 6 7 /*所有屬性的主盒子*/ 8 .commodity_attr_list { 9 background: #fff; 10 padding: 0 20rpx; 11 font-size: 26rpx; 12 overflow: hidden; 13 width: 100%; 14 } 15 /*每組屬性的主盒子*/ 16 .attr_box { 17 width: 100%; 18 overflow: hidden; 19 border-bottom: 1rpx solid #ececec; 20 } 21 /*屬性名*/ 22 .attr_name { 23 width: 20%; 24 float: left; 25 padding: 15rpx 0; 26 } 27 /*屬性值*/ 28 .attr_value_box { 29 width: 80%; 30 float: left; 31 padding: 15rpx 0; 32 overflow: hidden; 33 } 34 /*每一個屬性值*/ 35 .attr_value { 36 float: left; 37 padding: 0 10rpx; 38 margin: 0 10rpx; 39 border: 1rpx solid #ececec; 40 } 41 /*每一個屬性選中的當前樣式*/ 42 .attr_value_active { 43 background: #FFCC00; 44 border-radius: 10rpx; 45 color: #fff; 46 padding: 0 10rpx; 47 } 48 /*禁用屬性*/ 49 .attr_value_disabled { 50 color: #ccc; 51 } 52 53 /*button*/ 54 .btn-area { 55 margin: 1.17647059em 15px 0.3em; 56 } 57 58 .btn { 59 margin-top: 15px; 60 background-color:#FFCC00; 61 color: #fff; 62 } 63 .btn:first-child { 64 margin-top: 0; 65 }
js:this
數據部分,通常狀況都是訪問接口獲取數據的,這裏並無使用網絡訪問,爲了簡化demo,直接把一組數據放在data對象中。spa
1 Page({ 2 data: { 3 firstIndex: -1, 4 //準備數據 5 //數據結構:以一組一組來進行設定 6 commodityAttr: [ 7 { 8 priceId: 1, 9 price: 35.0, 10 "stock": 8, 11 "attrValueList": [ 12 { 13 "attrKey": "型號", 14 "attrValue": "2" 15 }, 16 { 17 "attrKey": "顏色", 18 "attrValue": "白色" 19 }, 20 { 21 "attrKey": "大小", 22 "attrValue": "小" 23 }, 24 { 25 "attrKey": "尺寸", 26 "attrValue": "S" 27 } 28 ] 29 }, 30 { 31 priceId: 2, 32 price: 35.1, 33 "stock": 9, 34 "attrValueList": [ 35 { 36 "attrKey": "型號", 37 "attrValue": "1" 38 }, 39 { 40 "attrKey": "顏色", 41 "attrValue": "黑色" 42 }, 43 { 44 "attrKey": "大小", 45 "attrValue": "小" 46 }, 47 { 48 "attrKey": "尺寸", 49 "attrValue": "M" 50 } 51 ] 52 }, 53 { 54 priceId: 3, 55 price: 35.2, 56 "stock": 10, 57 "attrValueList": [ 58 { 59 "attrKey": "型號", 60 "attrValue": "1" 61 }, 62 { 63 "attrKey": "顏色", 64 "attrValue": "綠色" 65 }, 66 { 67 "attrKey": "大小", 68 "attrValue": "大" 69 }, 70 { 71 "attrKey": "尺寸", 72 "attrValue": "L" 73 } 74 ] 75 }, 76 { 77 priceId: 4, 78 price: 35.2, 79 "stock": 10, 80 "attrValueList": [ 81 { 82 "attrKey": "型號", 83 "attrValue": "1" 84 }, 85 { 86 "attrKey": "顏色", 87 "attrValue": "綠色" 88 }, 89 { 90 "attrKey": "大小", 91 "attrValue": "大" 92 }, 93 { 94 "attrKey": "尺寸", 95 "attrValue": "L" 96 } 97 ] 98 } 99 ], 100 attrValueList: [] 101 }, 102 onShow: function () { 103 this.setData({ 104 includeGroup: this.data.commodityAttr 105 }); 106 this.distachAttrValue(this.data.commodityAttr); 107 // 只有一個屬性組合的時候默認選中 108 // console.log(this.data.attrValueList); 109 if (this.data.commodityAttr.length == 1) { 110 for (var i = 0; i < this.data.commodityAttr[0].attrValueList.length; i++) { 111 this.data.attrValueList[i].selectedValue = this.data.commodityAttr[0].attrValueList[i].attrValue; 112 } 113 this.setData({ 114 attrValueList: this.data.attrValueList 115 }); 116 } 117 }, 118 /* 獲取數據 */ 119 distachAttrValue: function (commodityAttr) { 120 /** 121 將後臺返回的數據組合成相似 122 { 123 attrKey:'型號', 124 attrValueList:['1','2','3'] 125 } 126 */ 127 // 把數據對象的數據(視圖使用),寫到局部內 128 var attrValueList = this.data.attrValueList; 129 // 遍歷獲取的數據 130 for (var i = 0; i < commodityAttr.length; i++) { 131 for (var j = 0; j < commodityAttr[i].attrValueList.length; j++) { 132 var attrIndex = this.getAttrIndex(commodityAttr[i].attrValueList[j].attrKey, attrValueList); 133 // console.log('屬性索引', attrIndex); 134 // 若是尚未屬性索引爲-1,此時新增屬性並設置屬性值數組的第一個值;索引大於等於0,表示已存在的屬性名的位置 135 if (attrIndex >= 0) { 136 // 若是屬性值數組中沒有該值,push新值;不然不處理 137 if (!this.isValueExist(commodityAttr[i].attrValueList[j].attrValue, attrValueList[attrIndex].attrValues)) { 138 attrValueList[attrIndex].attrValues.push(commodityAttr[i].attrValueList[j].attrValue); 139 } 140 } else { 141 attrValueList.push({ 142 attrKey: commodityAttr[i].attrValueList[j].attrKey, 143 attrValues: [commodityAttr[i].attrValueList[j].attrValue] 144 }); 145 } 146 } 147 } 148 // console.log('result', attrValueList) 149 for (var i = 0; i < attrValueList.length; i++) { 150 for (var j = 0; j < attrValueList[i].attrValues.length; j++) { 151 if (attrValueList[i].attrValueStatus) { 152 attrValueList[i].attrValueStatus[j] = true; 153 } else { 154 attrValueList[i].attrValueStatus = []; 155 attrValueList[i].attrValueStatus[j] = true; 156 } 157 } 158 } 159 this.setData({ 160 attrValueList: attrValueList 161 }); 162 }, 163 getAttrIndex: function (attrName, attrValueList) { 164 // 判斷數組中的attrKey是否有該屬性值 165 for (var i = 0; i < attrValueList.length; i++) { 166 if (attrName == attrValueList[i].attrKey) { 167 break; 168 } 169 } 170 return i < attrValueList.length ? i : -1; 171 }, 172 isValueExist: function (value, valueArr) { 173 // 判斷是否已有屬性值 174 for (var i = 0; i < valueArr.length; i++) { 175 if (valueArr[i] == value) { 176 break; 177 } 178 } 179 return i < valueArr.length; 180 }, 181 /* 選擇屬性值事件 */ 182 selectAttrValue: function (e) { 183 /* 184 點選屬性值,聯動判斷其餘屬性值是否可選 185 { 186 attrKey:'型號', 187 attrValueList:['1','2','3'], 188 selectedValue:'1', 189 attrValueStatus:[true,true,true] 190 } 191 console.log(e.currentTarget.dataset); 192 */ 193 var attrValueList = this.data.attrValueList; 194 var index = e.currentTarget.dataset.index;//屬性索引 195 var key = e.currentTarget.dataset.key; 196 var value = e.currentTarget.dataset.value; 197 if (e.currentTarget.dataset.status || index == this.data.firstIndex) { 198 if (e.currentTarget.dataset.selectedvalue == e.currentTarget.dataset.value) { 199 // 取消選中 200 this.disSelectValue(attrValueList, index, key, value); 201 } else { 202 // 選中 203 this.selectValue(attrValueList, index, key, value); 204 } 205 206 } 207 }, 208 /* 選中 */ 209 selectValue: function (attrValueList, index, key, value, unselectStatus) { 210 // console.log('firstIndex', this.data.firstIndex); 211 var includeGroup = []; 212 if (index == this.data.firstIndex && !unselectStatus) { // 若是是第一個選中的屬性值,則該屬性全部值可選 213 var commodityAttr = this.data.commodityAttr; 214 // 其餘選中的屬性值全都置空 215 // console.log('其餘選中的屬性值全都置空', index, this.data.firstIndex, !unselectStatus); 216 for (var i = 0; i < attrValueList.length; i++) { 217 for (var j = 0; j < attrValueList[i].attrValues.length; j++) { 218 attrValueList[i].selectedValue = ''; 219 } 220 } 221 } else { 222 var commodityAttr = this.data.includeGroup; 223 } 224 225 // console.log('選中', commodityAttr, index, key, value); 226 for (var i = 0; i < commodityAttr.length; i++) { 227 for (var j = 0; j < commodityAttr[i].attrValueList.length; j++) { 228 if (commodityAttr[i].attrValueList[j].attrKey == key && commodityAttr[i].attrValueList[j].attrValue == value) { 229 includeGroup.push(commodityAttr[i]); 230 } 231 } 232 } 233 attrValueList[index].selectedValue = value; 234 235 // 判斷屬性是否可選 236 for (var i = 0; i < attrValueList.length; i++) { 237 for (var j = 0; j < attrValueList[i].attrValues.length; j++) { 238 attrValueList[i].attrValueStatus[j] = false; 239 } 240 } 241 for (var k = 0; k < attrValueList.length; k++) { 242 for (var i = 0; i < includeGroup.length; i++) { 243 for (var j = 0; j < includeGroup[i].attrValueList.length; j++) { 244 if (attrValueList[k].attrKey == includeGroup[i].attrValueList[j].attrKey) { 245 for (var m = 0; m < attrValueList[k].attrValues.length; m++) { 246 if (attrValueList[k].attrValues[m] == includeGroup[i].attrValueList[j].attrValue) { 247 attrValueList[k].attrValueStatus[m] = true; 248 } 249 } 250 } 251 } 252 } 253 } 254 // console.log('結果', attrValueList); 255 this.setData({ 256 attrValueList: attrValueList, 257 includeGroup: includeGroup 258 }); 259 260 var count = 0; 261 for (var i = 0; i < attrValueList.length; i++) { 262 for (var j = 0; j < attrValueList[i].attrValues.length; j++) { 263 if (attrValueList[i].selectedValue) { 264 count++; 265 break; 266 } 267 } 268 } 269 if (count < 2) {// 第一次選中,同屬性的值均可選 270 this.setData({ 271 firstIndex: index 272 }); 273 } else { 274 this.setData({ 275 firstIndex: -1 276 }); 277 } 278 }, 279 /* 取消選中 */ 280 disSelectValue: function (attrValueList, index, key, value) { 281 var commodityAttr = this.data.commodityAttr; 282 attrValueList[index].selectedValue = ''; 283 284 // 判斷屬性是否可選 285 for (var i = 0; i < attrValueList.length; i++) { 286 for (var j = 0; j < attrValueList[i].attrValues.length; j++) { 287 attrValueList[i].attrValueStatus[j] = true; 288 } 289 } 290 this.setData({ 291 includeGroup: commodityAttr, 292 attrValueList: attrValueList 293 }); 294 295 for (var i = 0; i < attrValueList.length; i++) { 296 if (attrValueList[i].selectedValue) { 297 this.selectValue(attrValueList, i, attrValueList[i].attrKey, attrValueList[i].selectedValue, true); 298 } 299 } 300 }, 301 /* 點擊肯定 */ 302 submit: function () { 303 var value = []; 304 for (var i = 0; i < this.data.attrValueList.length; i++) { 305 if (!this.data.attrValueList[i].selectedValue) { 306 break; 307 } 308 value.push(this.data.attrValueList[i].selectedValue); 309 } 310 if (i < this.data.attrValueList.length) { 311 wx.showToast({ 312 title: '請完善屬性', 313 icon: 'loading', 314 duration: 1000 315 }) 316 } else { 317 wx.showToast({ 318 title: '選擇的屬性:' + value.join('-'), 319 icon: 'sucess', 320 duration: 1000 321 }) 322 } 323 } 324 })
運行效果:code