电商小程序 -- 商品多规格选择弹框

最近在搞一个电商小程序,一个月左右入门到放弃

  • 直接上效果图
  • 商品规格选择功能
    • 1, choose.js文件
    • 2, choose.json 文件(*没用的)
    • 3, choose.wxml 布局文件
    • 4, choose.wcss 样式文件

直接上效果图

电商小程序 -- 商品多规格选择弹框_第1张图片

商品规格选择功能

  • 代码结构
    电商小程序 -- 商品多规格选择弹框_第2张图片
  • 通过npm导入lodash库结构,这个就不细说了
    电商小程序 -- 商品多规格选择弹框_第3张图片

1, choose.js文件

// choose/choose.js
const lodash = require('../miniprogram_npm/lodash/index.js')//路径是相对的
Page({

  /**
   * 页面的初始数据
   */
  data: {
    //进来时,默认的显示价格
    price:25,
    origin_price: 45,

    allMoney: 0,
    allMoneyOrigin: 0,
    chooseAttrIndex: [0, 0, 0],
    chooseAttrName: ['', '', ''],
    chooseData: {},
    goodsID: {},
    chooseAttr: '',
    buyNumber:1,
    img:'http://groupon-1257844634.cos.ap-guangzhou.myqcloud.com/goods/2019/08/114042-5d4b99ba01589.jpeg',
    attrCount: 0,//属性个数
    attrsHidden: true,//规格弹框是否隐藏
    //所有属性
    dataAttr: { "code": 0, "msg": "操作成功", "data": { "list": [{ "attr_id": "16", "name": "颜色", "vals": [{ "val_id": "16", "name": "红色" }, { "val_id": "17", "name": "白色" }] }, { "attr_id": "17", "name": "内存", "vals": [{ "val_id": "18", "name": "4G" }] }, { "attr_id": "18", "name": "存储空间", "vals": [{ "val_id": "21", "name": "16G" }, { "val_id": "22", "name": "32G" }, { "val_id": "23", "name": "64G" }] }] } },

    //各个属性对应商品的sku
    dataSkus: { "code": 0, "msg": "操作成功", "data": { "total_page": 1, "current_page": "1", "list": [{ "sku": "nb00101", "origin_price": "50.00", "price": "30.00", "stock": 12, "goods_attr": "16,17,18", "goods_attr_val": "16,18,21" }, { "sku": "nb00102", "origin_price": "55.00", "price": "35.00", "stock": 8, "goods_attr": "16,17,18", "goods_attr_val": "16,18,22" }, { "sku": "nb00103", "origin_price": "45.00", "price": "25.00", "stock": 8, "goods_attr": "16,17,18", "goods_attr_val": "16,18,23" }, { "sku": "nb00104", "origin_price": "50.00", "price": "30.00", "stock": 8, "goods_attr": "16,17,18", "goods_attr_val": "17,18,21" }, { "sku": "nb00105", "origin_price": "55.00", "price": "35.00", "stock": 8, "goods_attr": "16,17,18", "goods_attr_val": "17,18,22" }] } }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    this.setData({
      goodsGG: this.data.dataAttr.data.list,
      goodsID: this.data.dataSkus.data.list,
      attrCount: this.data.dataAttr.data.list.length
    })

    //进来时设置默认的最低价
    this.setData({
      allMoney: this.data.price,
      allMoneyOrigin: this.data.origin_price
    })
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },
  // 规格属性显示/隐藏
  popUpAttr: function (res) {
    if (res == 0) {
      this.setData({
        act_id: 0
      })
    }

    this.setData({
      attrsHidden: !this.data.attrsHidden
    })
  },
  //属性选择
  choosingAttr: function (e) {
    let clickD = e.currentTarget.dataset
    let keyIntro = 'chooseAttrIndex[' + clickD.row + ']'
    let nameIntro = 'chooseAttrName[' + clickD.row + ']'
    let dataIntro = {}
    dataIntro[keyIntro] = clickD.attrValue
    dataIntro[nameIntro] = clickD.attrName
    this.setData(dataIntro)
    let choosingAttr = lodash.compact(this.data.chooseAttrIndex)//去除数据中的空数据

    if (choosingAttr.length == this.data.attrCount) {//通过长度判断是否选齐属性
      let attrString = lodash.join(choosingAttr, ',')//转回连接字符串,用逗号","隔开
      let choosingGoods = lodash.find(this.data.goodsID, function (o) {//找到返回脚标,找不到返回-1
        return o.goods_attr_val == attrString;
      })
      // console.log(choosingGoods, choosingGoods.price) //
      
      try {//处理库存问题,所选属性对应的sku
        this.setData({
          chooseData: choosingGoods,
          allMoney: choosingGoods.price * this.data.buyNumber,//选择属性对应的真实售价
          allMoneyOrigin: choosingGoods.origin_price * this.data.buyNumber//选择属性对应的定价
        })
      } catch (e) {//如果goodsID中没有对应的sku,就进来这里
        this.showToast('该商品已卖光了', 'none')
        //将原已选规格清空
        this.setData({
          chooseAttrIndex: [],
          chooseAttr: [],
          allMoney: this.data.price,
          allMoneyOrigin: this.data.origin_price
        })
        //直接返回
        return
      }
    }
    // console.log(this.data.chooseAttrName)
    let choosingAttrName = lodash.compact(this.data.chooseAttrName); //去除数据中的空数据
    this.setData({
      chooseAttr: lodash.compact(this.data.chooseAttrName)//去除数据中的空数据
    });
    // console.log(choosingAttrName)
  },
  
  //数量减1
  subtractNumber: function () {
    //选好规格,再选数量
    let choosingAttr = lodash.compact(this.data.chooseAttrIndex)
    if (choosingAttr.length != this.data.attrCount) {//如果属性规格还没选齐,就不执行数量的增减
      this.showToast("请选择属性", 'none');
      return
    }

    var buyNumber = this.data.buyNumber;
    if (buyNumber <= 1) {
      this.setData({
        buyNumber: 1
      });
      return;
    }
    buyNumber--;
    this.setData({
      buyNumber: buyNumber,
      allMoney: this.data.allMoney * buyNumber,
      allMoneyOrigin: this.data.allMoneyOrigin * this.data.buyNumber
    });
  },
  //数量加1
  addNumber: function () {
    //选好规格,再选数量
    let choosingAttr = lodash.compact(this.data.chooseAttrIndex)
    if (choosingAttr.length != this.data.attrCount) {//如果属性规格还没选齐,就不执行数量的增减
      this.showToast("请选择属性", 'none');
      return
    }

    var buyNumber = this.data.buyNumber;
    buyNumber++;
    this.setData({
      buyNumber: buyNumber,
      allMoney: this.data.allMoney * buyNumber,
      allMoneyOrigin: this.data.allMoneyOrigin * this.data.buyNumber
    });
  },

  //去开团
  toGroupBuying: function () {

    let choosingAttr = lodash.compact(this.data.chooseAttrIndex)
    if (choosingAttr.length != this.data.attrCount) {
      this.showToast("请选择属性", 'none');
      return;
    }

    this.showToast("属性选择完成", 'none');
  },

  //弹出提示框
  showToast:function (msg, status) {
    wx.showToast({
      title: msg,
      icon: status,
      duration: 2000
    })

    var params = new Object();
    params.goods_img = this.data.img;
    params.specs = lodash.compact(this.data.chooseAttrName);
    params.sku = this.data.chooseData.sku;
    params.buyNumber = this.data.buyNumber;
    params.allMoney = this.data.allMoney;
    params.allMoneyOrigin = this.data.allMoneyOrigin;

    console.log(JSON.stringify(params));
  }
})

2, choose.json 文件(*没用的)

{
  "usingComponents": {}
}

3, choose.wxml 布局文件

<!--choose/choose.wxml-->
<button bindtap='popUpAttr'>点我试试</button>

<!-- 商品规格框 -->
<view catchtouchmove="ture" class="popUpAttrs" hidden="{{attrsHidden}}">

  <view class="popUpAttrs lucency" bindtap='popUpAttr'></view>

  <view class="popUpAttrsContainer" bindtap='returnNull' catchtap="ture">
    <view class='moneyNumber toTop'>
      <view>
        <view class='toRows'>
          <image style='width:80px;height:80px;margin-left:10px;margin-right:10px;border-radius: 4rpx;background:#453330;' src="{{img}}"></image>
          <view>
            <view style="margin-top:10px">
              <text class="money">¥{{allMoney}}</text>
              <text class="moneyShow">¥{{allMoneyOrigin}}</text>
            </view>
            <view style='color:#474747;font-size:12px;font-weight:bold;margin-top:2px'>已选:{{chooseAttr}}</view>
          </view>
        </view>
      </view>
    </view>

    <view class='hr1' style="margin-top:10px;margin-bottom:10px;"></view>
    <view style="padding-left:15px;padding-right:15px;">
      <block wx:for="{{goodsGG}}" wx:for-item="item" wx:key="index" wx:for-index="row">
        <text style="font-size: 14px;">{{item.name}}</text>
        <view style="margin-bottom:15px;margin-top:10px">
          <block class="indexItem" wx:for="{{item.vals}}" wx:for-item="item2" wx:key='index' wx:for-index="columns">
            <text class="{{(row == 0 && chooseAttrIndex[0] == item2.val_id) ? 'choosingFlagsAttrs' : ((row == 1 && chooseAttrIndex[1] == item2.val_id) ? 'choosingFlagsAttrs' : ((row == 2 && chooseAttrIndex[2] == item2.val_id) ? 'choosingFlagsAttrs' : 'flagsAttrs' ))}}"
              style="font-size: 12px;" bindtap='choosingAttr' data-attr-name="{{item2.name}}" data-attr-value="{{item2.val_id}}" data-row="{{row}}" data-columns="{{columns}}">{{item2.name}}</text>
          </block>
        </view>
      </block>
    </view>
    <view class='hr1' style="margin-top:10px;"></view>
    <view class='moneyNumber' style="padding-right:10px;padding-left:10px;margin-bottom:20px;">
      <view style="font-size: 14px;">购买数量</view>
      <view class="rowLayout" style="width:auto;">
        <view bindtap="subtractNumber" class="join" style="width:30px;height:30px;background:#F7F7F7;border:1px solid rgba(236,238,240,1);color:black;">-</view>
        <view class="join" style="width:30px;height:30px;background:#fff;border:1px solid rgba(236,238,240,1);color:#8C8D8F;">{{buyNumber}}</view>
        <view bindtap="addNumber" class="join" style="width:30px;height:30px;background:#F7F7F7;border:1px solid rgba(236,238,240,1);color:black;">+</view>
      </view>
    </view>

    <view class='buttomItem join orangeBtm' bindtap='toGroupBuying'>立刻购买</view>
  </view>
</view>

4, choose.wcss 样式文件

/* choose/choose.wxss */
.hr1 {
  background: rgba(247, 247, 247, 1);
  width: 100%;
  height: 1px;
  margin-left: 15rpx;
}
/* 规格弹出层 */

.popUpAttrs {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: 0;
  display: flex;
}

/* 规格弹出层内容区 */

.popUpAttrsContainer {
  display: flex;
  flex-flow: column;
  position: fixed;
  background: white;
  bottom: 0;
  width: 100%;
  height: auto;
  border-radius: 8rpx 8rpx 0 0;
  font-size: 28rpx;
  padding-bottom: 56px;
  z-index: 999999;
}

/* 立刻购买 */

.orangeBtm {
  background: #dc7968;
}

.lucency {
  background: transparent;
  background-color: transparent;
}

.moneyNumber {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20rpx;
}

.orangeBtm {
  background: #dc7968;
}

.toTop {
  margin-top: -32rpx;
}

/* 居中横排 */
.toRows {
  display: flex;
  flex: row;
  align-items: center;
}

.money {
  color: #dc7968;
  font-size: 19px;
  margin-right: 10px;
}

.moneyShow {
  color: #b4b4b4;
  font-size: 14px;
  text-decoration-line: line-through;
}

/* 标签外层 */

.indexItem {
  width: auto;
  height: auto;
  display: flex;
  flex-direction: row;
}

/* 标签 */
.choosingFlagsAttrs {
  background: white;
  border-radius: 5rpx;
  color: white;
  background: #dc7968;
  padding: 16rpx;
  font-size: 12px;
  margin-right: 15rpx;
}

.flagsAttrs {
  background: white;
  border-radius: 5rpx;
  color: black;
  background: #f5f5f5;
  padding: 16rpx;
  font-size: 12px;
  margin-right: 15rpx;
}

.rowLayout {
  width: 50%;
  display: flex;
  flex-direction: row;
  align-items: center; /**子view垂直居中*/
  padding: 10rpx;
  justify-content: space-evenly;
}

.join {
  display: flex; /*设置显示样式**/
  align-items: center; /**子view垂直居中*/
  vertical-align: center; /**垂直居中*/
  justify-content: center; /**内容居中*/
  flex-direction: row;
  width: 50%;
  height: 100%;
  background: #dc7968;
  font-size: 16px;
  color: white;
}


/* 底部条 */

.buttomItem {
  display: flex;
  flex-flow: row;
  width: 100%;
  height: 100rpx;
  position: fixed;
  background: white;
  bottom: 0;
  /* bottom:0; 底部固定 *//* top:0; 顶部固定 */
}

.orangeBtm {
  background: #dc7968;
}

  • 所有的主要代码已经在上面了

  • 附录 package.json文件

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "lodash": "^4.17.15"
  }
}
  • 当lodash出错(lodash版本号:4.17.15)
    电商小程序 -- 商品多规格选择弹框_第4张图片

  • 解决办法

  • 将miniprogram_npm/lodash/index.js

var root = freeGlobal || freeSelf || Function('return this')();
  • 改成为:
var root = {
  Array: Array,
  Date: Date,
  Error: Error,
  Function: Function,
  Math: Math,
  Object: Object,
  RegExp: RegExp,
  String: String,
  TypeError: TypeError,
  setTimeout: setTimeout,
  clearTimeout: clearTimeout,
  setInterval: setInterval,
  clearInterval: clearInterval
};

你可能感兴趣的:(小程序)