总体结构猜测
重点结构(sku_list)
sku_list 是一个数组类型的数据,里面包含的是一个个对象,每个对象都是一个 sku
<m-sku-list list="{{sku_list}}" defaultSkuId="{{default_sku_id}}"></m-sku-list>
我们已经有了数据,分析一下页面结构
如下图:我们需要一个容器承接 sku详情数据,另个容器承接 sku 规格数据
详情数据好说,都是现成直接往里填充就好,但是规格就没有现成的可以使用了,因此我们需通过分析规格数据格式抽象一个 用于一定规格的对象来帮助我们搭建容器
// 抽象规格数据 // 如上图,一共有三种分类(颜色、款式、尺码),三种分类各自组合成一个sku,这样多个数据的情况下适用数组管理 // 每种规格都被视作一个对象,对象包含 标题、分类id、组合合成的规格 component({ data:{ specsList:[] // 规格列表用于搭建框架 } })
component({ ..., observers:{ "list":function(list){ // 防空 if (list.length === 0) return // 搭建 spu 规格模板 const specList = list[0].specs.map(item => { return { keyId:item.key_id, key:item.key, category:[] } }) // 填充 sku 规格模板 specList.map(m => { // 获取各个规格 list.map(i => { // 获取规则中一种分类对应的所有样式,例如:颜色:红、白、蓝 const category = i.specs.find(spec => { return m.keyId === spec['key_id'] }) // 防止重复保存相同的样式 if(m.category.length === 0) { m.category.push(category) } else { const b = m.category.find(c => c["value_id"] === category['value_id']) if(!b) m.category.push(category) } }) }) } } })
交互逻辑有很多,在显示之前我先将其一一列出来,以防后思维混乱
分析选中与取消选中
component({ data:{ ..., // 根据上述分析,我们需要一个数组来管理选中状态 selectedList:[] }, ... methods:{ // 点击触发切换样式 selectedSku(e) { // 切换样式,我们也需要知道,我们当前点击的是哪个样式(category),disable是禁选 const {category,disable} = e.currentTarget.dataset if (disable) return // 获取当前选中样式的列表 const arr = this.data.currentSelect // 判断是否点选已选中的样式 // 获取当前选中的样式分类 const index = arr.findIndex((item,index) => { return item['key_id'] === sku['key_id'] }) // 简单逻辑判断 if (index === -1) { // 列表中没有该分类 arr.push(sku) }else { // 列表中已有该分类,那就是取消选中或,更换选中 if (sku['value_id'] === arr[index]['value_id']) { arr.splice(index,1) }else { arr.splice(index,1,sku) } } this.setData({ currentSelect:arr }) }, } })
<view class=" category-item <!-- 默认样式 --> {{m.selected(item['key_id'],item['value_id'],currentSelect) ? 'active' : ''}} <!-- 选中样式 --> {{m.isDisable(currentSelect,item,allSku,maxSelectSize) ? 'disable':''}}" <!-- 禁用样式 --> data-category="{{item}}" <!-- 当前 item 携带的样式信息 --> data-disable="{{m.isDisable(currentSelect,item,allSku,maxSelectSize)}}" <!-- 判断 item 是否已禁用 --> bind:tap="selectedSku"> <!-- 点击触发选中 --> <view class="category-item-inner">{{item.value}}</view> </view> <wxs module="m"> ... var isDisable = function (currentSelect,item,allSku,maxSize) { var flag = true // 当前选项长度是 0 if (currentSelect.length === 0) { flag = false } else if (currentSelect.length === maxSize) { // 当前选项长度是最大选项值时,item 若非选中则禁用 currentSelect.forEach(function (c){ // console.log("wx",c['key_id'] === item['key_id']) if (c['key_id'] === item['key_id']){ if (c['value_id'] === item['value_id']) { flag = false } } }) } else if (currentSelect.length === 1) { // 当前选项长度是只有 1 个时 // 相同类型可选 if (currentSelect[0]['key_id'] === item['key_id']){ flag = false return } // 非相同类型需要判断 allSku.filter(function (s) { var cv = currentSelect[0]['value_id'].toString() // console.log(s[cv] , currentSelect[0]['value']) return s[cv] === currentSelect[0]['value'] }).forEach(function (s) { var v = item['value_id'].toString() if (s[v] === item['value']) { flag = false } }) } else { // 当前选项长度大于 1 小于 最大选项值时 // 先从所有 sku 中过滤出符合当前选中的 sku var filterSku = [] currentSelect.forEach(function (cs) { filterSku = allSku.filter(function (s) { var cv = cs['value_id'].toString() // console.log(s[cv] , currentSelect[0]['value']) return s[cv] === cs['value'] }) }) // 当 item 与 选中列表中的样式组合 能在 sku 列表中找到 filterSku.forEach(function (fs) { var v = item['value_id'].toString() if (fs[v] === item['value']) { flag = false } }) } return flag } module.exports = { ..., isDisable:isDisable, } </wxs>
component({ ..., observers: { ..., "currentSelect":function (currentSelect) { if (currentSelect.length === this.data.maxSelectSize) { // 获取数据 const {allSku} = this.data const {list} = this.properties // 筛选sku let filter = allSku currentSelect.map(cs =>{ filter = filter.filter(f => { return f[cs['value_id'].toString()] === cs['value'] }) }) // 未筛选中,返回 if (filter.length === 0) return // 筛选中 const sku = list.find(item => { return item.id === filter[0].id }) this.setData({ currentSku:sku }) } } } })