微信小程序之商品属性分类
所提及的购物数量的加减,现在说说商品属性值联动选择。
为了让同学们有个直观的了解,到电商网截了一个图片,就是红圈所示的部分
现在就为大家介绍这个小组件,在小程序中,该如何去写
下图为本项目的图:
wxml:
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:
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:
数据部分,一般情况都是访问接口获取数据的,这里并没有使用网络访问,为了简化demo,直接把一组数据放在data对象中。
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 })
运行效果: