基于LinUI组件实现SPU商品选择

1. 效果图

1
2
3

数据格式

{
  "id": 2,
  "title": "林间有风自营针织衫",
  "subtitle": "秋日冬款,浪漫满屋",
  "category_id": 12,
  "root_category_id": 2,
  "price": "77.00",
  "img": "http://i1.sleeve.7yue.pro/assets/ecf8d824-19d4-4db2-a5da-872ab014fecd.png",
  "for_theme_img": "https://gitee.com/lrelia7/sleeve-static/raw/master/theme/spu1.png",
  "description": null,
  "discount_price": "62.00",
  "tags": "秋日冬款$浪漫满屋",
  "is_test": true,
  "online": true,
  "sku_list": [{
    "id": 2,
    "price": 77.76,
    "discount_price": null,
    "online": true,
    "img": "http://i1.sleeve.7yue.pro/assets/2d22ffec-b1c1-43e0-ad21-25aa5c26ab34.png",
    "title": "金属灰·七龙珠",
    "spu_id": 2,
    "category_id": 17,
    "root_category_id": 3,
    "specs": [{
      "key_id": 1,
      "key": "颜色",
      "value_id": 45,
      "value": "金属灰"
    }, {
      "key_id": 3,
      "key": "图案",
      "value_id": 9,
      "value": "七龙珠"
    }, {
      "key_id": 4,
      "key": "尺码",
      "value_id": 14,
      "value": "小号 S"
    }],
    "code": "2$1-45#3-9#4-14",
    "stock": 5
  }],
  "spu_img_list": [{
    "id": 165,
    "img": "http://i1.sleeve.7yue.pro/assets/5605cd6c-f869-46db-afe6-755b61a0122a.png",
    "spu_id": 2
  }],
  "spu_detail_img_list": [{
    "id": 24,
    "img": "http://i2.sleeve.7yue.pro/n4.png",
    "spu_id": 2,
    "index": 1
  }],
  "sketch_spec_id": 1,
  "default_sku_id": 2
}

2. Lin-UI组件

Lin-UI Grid组件文档

3. 实现思路

3.1. 将数据中的规格与规格值过滤出来

3.2 使用Lin-UI的l-grid与l-grid-item组件遍历规格与规格值来实现列表

  1. 将规格值得id来充当l-grid-item的key
  2. 设置点击事件, 可获取当前点击的规格值id
// 点击事件
getGrid: function(e) {
    const valueId = e.detail.key
    if (this.data.disable.indexOf(parseInt(valueId)) === -1) {
      return;
    }
    // 选中/反选
    const selects = this._select(valueId);
    // 禁用
    const disable = this._disable(selects);
    this.setData({
      selects,
      disable
    });

  },

3.3 使用wxs与三元运算符实现默认/选中/禁用不同的样式

3.3.1 选中/反选
  1. 声明两个数组 select 数组与 disable数组
  2. 当select数组中有对应规格值id时表示当前规格值已选中
  3. 每次点击时触发事件将当前规格值id放入select数组中, 反选时再将当前规格值id移除
  4. 同规格的规格值时只能选择一个
  /**
   * 选中/反选
   * @param valueId
   * @returns {Array}
   * @private
   */
  _select(valueId) {
    const selects = this.data.selects; //选中数组
    let specDisables= this.data.specDisables;
    //找出valueId所在的规格id分组
    let ds = [];
    for (var spec of specDisables) {
      if (spec.indexOf(parseInt(valueId)) > -1) {
        ds = ds.concat(spec);
      }
    }
    // 判断已选中的数组中是否有 valueId的同组规格id 如果有则删除select数组的规格值id
    for (var d of ds) {
      if (selects.indexOf(d.toString()) > -1 && d !== parseInt(valueId)) {
        selects.splice(this._arrays(d, selects), 1);
      }
    }

    if (selects.indexOf(valueId) === -1) { //如果当前规格id不存在 添加
      selects.push(valueId);
      return selects;
    }
    selects.splice(this._arrays(valueId, selects), 1); //如果存在 删除
    return selects;
  },
3.3.2 禁用
  1. disable数组默认所有规格值id, 当规格值id不存在时禁用
  2. 不能点击, 每次进入点击事件时判断disable数组中是否有当前点击的规格值id, 如果不存在直接return
  3. 每次点击时触发事件通过select数组中已选中的规格值id来筛选出可用的规格值, 并放入到disable数组中
  /**
   * 禁用
   * @param selects
   * @returns {Array}
   * @private
   */
  _disable(selects) {
    let skuDisables = this.data.skuDisables;
    let specDisables= this.data.specDisables;
    let disables = [];
    let disable = [];
    if (selects.length === 0) {
      disable = this.data.specValueIds;
    }
    for (var se of selects) {
      let ds = [];
      for (var sku of skuDisables) {
        if (sku.indexOf(parseInt(se)) > -1) {
          ds = ds.concat(sku);
        }
      }
      for (var spec of specDisables) {
        if (spec.indexOf(parseInt(se)) > -1) {
          ds = ds.concat(spec);
        }
      }
      disables.push(ds);
    }
    console.log(disables);
    for (var dis of disables) {
      if (disable.length === 0) {
        disable = dis;
        continue;
      }
      disable = this._intersect(disable,dis); //交集
    }
    return disable;
  },

看这个之前先去项目中观察完整的数据格式 jsonData

  1. 获取到数据时把 数据按照每个sku不同的规格分别进行分组( 例如 [45, 9, 14]是一组规格值id组成的一个sku. [45, 42, 42, 44]是所有规格id为1的规格值id )
  2. 当选中规格值为45时, 从sku的分组来看包含45的分组为[45, 9, 14] 从规格分组来看( 同种规格 ) 包含45的是[45, 42, 42, 44] 所以可选规格值为[45, 9, 14, 42, 44]
  3. 当选中规格值为45, 14时, 同理包含14的sku分组[44,8,14]和[45, 9, 14] 规格分组[14, 15, 16, 14] 因为45与14规格值要同时满足才是可选状态所以要取交集并去重得出可选规格值[45, 14, 9, 44]
    禁用思路草稿

4. wxml代码

<wxs src="./tools.wxs" module="tools" />

<view class="container">

    <block wx:for="{{specKeyIds}}" wx:for-item="item">
        <view class="container-item">
            <view  class="item-text">{{item.key}}</view>
            <l-grid bind:linitemtap="getGrid" is-hover="{{false}}" row-num="4" l-class="grid">
                <block wx:for="{{specArrays}}" wx:for-item="spec" >
                    <l-grid-item wx:if="{{spec.key_id == item}}" key="{{spec.value_id}}" slot="{{spec.value_id}}" l-grid-item-class="l-grid-item">
                        <view class="{{tools.disable(disable,spec.value_id) ? 'grid-item-disable' : tools.includes(selects,spec.value_id) ? 'grid-item-select':'grid-item'}} ">
                            <view class="{{tools.disable(disable,spec.value_id) ? 'item-disable' : tools.includes(selects,spec.value_id) ? 'item-select':'item'}}">
                                <image wx:if="{{spec.key_id == 1}}" class="item-img" src="{{spec.img}}"></image>
                                <text class="{{tools.disable(disable,spec.value_id) ? 'item-text-disable' : tools.includes(selects,spec.value_id) ? 'item-text-select':'item-text'}}">{{spec.value}}</text>
                            </view>
                        </view>
                    </l-grid-item>
                </block>
            </l-grid>
        </view>
    </block>
</view>

5. wxs代码

module.exports.disable =  function(disableSpecs, valueId){
  return disableSpecs.indexOf(valueId) === -1

}

module.exports.includes =  function(selectSpecs, spec) {
  return selectSpecs.indexOf(spec.toString()) > -1;
}

5. 代码地址

https://gitee.com/winnxudong/lin_lessons

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355