小程序购物车功能实现【详解】

购物车列表的数据是调取后台接口拿到的,在这里有一个问题就是:调取购物车列表接口到底是在哪个声明周期执行???

最开始我是写在onLoad里边的,后来在测试的时候发现一个问题,从购物车页面进入到商品详情页面,添加商品到购物车之后再回到购物车页面,发现刚刚添加的商品并没有显示在购物车里,但是添加到购物车这个操作确实是成功了的。这是什么原因呢?

因为我的 购物车页面是tabBar的页面,只有在第一次进入这个页面的时候才会加载,这也是为什么我在onLoad里边console.log一个数值,在再次进入购物车这个页面的时候并不会打印输出的原因。只需要把 获取购物车列表数据的方法写在onShow这个生命周期里 就好了。

下面是购物车获取数据方法:
小程序购物车功能实现【详解】_第1张图片

首先我们需要了解购物车页面的功能需求:

  1. 进入购物车页面默认全选状态,合计金额为所有商品的金额
  2. 取消选择任何一个商品全选状态都要取消
  3. 当购物车所有的商品都被勾选时,自动触发全选按钮
  4. 购物车商品数量变化的时候。合计金额要随之变化
  5. 点击全选按钮的时候,所有商品的状态全部为选中状态。且合计金额为所有商品金额
  6. 当删除商品的时候,如果是已经勾选的商品,商品的合计金额要发生变化

考虑到 合计价格变化多处都有用到,我们最好将其封装成一个单独的方法。

  // 合计金额方法
  totalPrice:function(){
    var totalPrice=0;
    for(var i=0;i<this.data.chooseGoods.length;i++){
      totalPrice += this.data.chooseGoods[i].goods_price * this.data.chooseGoods[i].goods_number-0;
    }
    this.setData({totalPrice:totalPrice.toFixed(2)});
  },

默认状态很好实现,我们已经在data里定义了一个变量 is_chooseAll 用来控制全选的状态,合计金额就是每一条数据中 单价*数量 的和,当然我们已经封装了求合计金额的方法,在 onShow 的生命周期里直接调用就好了。
在计算的时候要注意js计算小数容易出错的问题。

在获取购物车数据的时候我们已经手动在每一条数据里添加了一个用于标记是否勾选的标记flag,所以选中与否的状态改变就很好控制了,我们只需要改变对应商品的flag值就可以了,当然我们需要获取到勾选商品的index。

功能点2和3 都是在勾选单个商品的时候发生的,我们就可以在同一个方法里实现这两个功能。
我是在每次勾选的时候把选中的商品添加到一个新的数组chooseGoods当中,取消勾选的时候同样的去删除这个新数组中对应的数据,当然在计算总金额的方法中也是去循环去计算这个数组中每一条的价格然后求和。

  // 选择商品
  chooseThis:function(e){
    var index=e.currentTarget.dataset.index;   //获取勾选商品的index

    var chooseGoods=this.data.chooseGoods;

    var cartData=this.data.cartData;
    var this_flag = cartData.cart_goods[index].flag;

    /*判断flag的值
      如果此时flag==1代表当前执行操作是取消勾选
      如果此时flag==0代表当前执行操作是勾选
    */
    //删除数据  
    if(this_flag==1){
      cartData.cart_goods[index].flag=0;   //先把flag重置为0

      // 用index去和chooseGoods里边每一条数据的索引值做对比,删除匹配成功的那条数据
      for(var i=0;i<chooseGoods.length;i++){
        if (chooseGoods[i].rec_id == cartData.cart_goods[index].rec_id){
          chooseGoods.splice(i,1);
        }
      }
    }

    //添加数据
    else{
      cartData.cart_goods[index].flag = 1;
      chooseGoods.push(cartData.cart_goods[index]); 
    }

    // 取消全选操作
    var is_chooseAll=this.data.is_chooseAll;

    /*循环获取到的购物车列表每一项的flag值,
      如果有一个flag为0,就取消全选
      如果每一项的值都为1,那么就触发全选操作
    */
    for (var j = 0; j < cartData.cart_goods.length;j++){
      // 有一个没选中就取消全选
      if (cartData.cart_goods[j].flag==0){
          is_chooseAll=0;
          break;
      }else{
        if(chooseGoods.length==cartData.cart_goods.length){
          is_chooseAll = 1;
        }
      }
    }

    this.setData({
      cartData:cartData,
      chooseGoods:chooseGoods,
      is_chooseAll:is_chooseAll
    });

    this.totalPrice();
  },

删除某一个商品的功能主要是调了一个后台接口实现的,但是有一点要考虑的是,删除的数据有可能是我们之前已经勾选(已经添加到chooseGoods数组中)的,调用接口删除返回新的购物车列表数据并不会改变这个数组中的数据,所以我们在删除的时候才需要用删除数据的index去chooseGoods数组中去匹配一下有没有已勾选的数据,有的话删除对应的数据。

// 删除方法
  delete:function(e){
    var that=this;

    var cartData=this.data.cartData;
    var chooseGoods=this.data.chooseGoods;

    app.ajax(
      'cart/delCartGoods',
      'post',
      function(res){
        console.log(res);
        if (res.data.code == 200){

          // 删除已勾选的数据
          for (var i = 0; i < chooseGoods.length; i++) {
            if (cartData.cart_goods[e.currentTarget.dataset.index].rec_id == chooseGoods[i].rec_id) {
              chooseGoods.splice(i, 1);
            }
          }

          cartData.cart_goods.splice(e.currentTarget.dataset.index, 1);

          that.setData({
            'cartData': cartData,
            'chooseGoods': chooseGoods
          });

          that.totalPrice();

        }else{
          wx.showToast({
            title: res.data.msg,
            icon:'none'
          })
        }
      },
      {
        rec_id: cartData.cart_goods[e.currentTarget.dataset.index].rec_id,
        leader_id:app.globalData.leader_id
      }
    )
  },

商品数量的更改也同样包括两个部分,原始列表数据中对应商品数量的更改和chooseGoods数组中对应商品数量的更改,这里就需要判断修改数量的产品是否在chooseGoods数组当中,同删除方法。不要忘记在更改数量的时候调用计算合计金额的方法。

// 商品数量增减接口
  getLeftNum:function(e){
    var that=this;
    var cartData = this.data.cartData;
    var type = e.currentTarget.dataset.type;
    var index = e.currentTarget.dataset.index;
    var rec_id = e.currentTarget.dataset.rec_id;

    var chooseGoods=this.data.chooseGoods;
    
    // 数量增加
    if(type=='add'){
      cartData.cart_goods[index].goods_number++;
    }
    // 数量减少
    else{
      if (cartData.cart_goods[index].goods_number>1){
        cartData.cart_goods[index].goods_number--;
      }
    }

    // 更新chooseGoods中变化的数量
    for(var i=0;i<chooseGoods.length;i++){
      if(chooseGoods[i].rec_id==cartData.cart_goods[index].rec_id){
        chooseGoods[i].goods_number=cartData.cart_goods[index].goods_number;
      }
    }
    
    app.ajax(
      'cart/changeNumber',
      'post',
      function(res){
        console.log(res);
      },
      {
        leader_id:app.globalData.leader_id,
        rec_id:rec_id,
        number: cartData.cart_goods[index].goods_number
      }
    );

    this.setData({ 
      cartData: cartData,
      chooseGoods:chooseGoods
    });

    this.totalPrice();
  },

在执行全选操作的时候,首先要判断当前状态是否是全选,全选状态是通过is_chooseAll来控制的,is_chooseAll=0不全选,is_chooseAll=1全选。我们的合计金额是根据chooseGoods这个数组来计算的,所以在全选的时候要使chooseGoods等于原始数组。

// 全选
  chooseAll:function(){
    var is_chooseAll=this.data.is_chooseAll;
    var cartData=this.data.cartData;
    var chooseGoods=this.data.chooseGoods;

    // 当前是不全选状态 点击触发全选  ——————  要把状态修改为全选且chooseGoods=原始数组
    if(is_chooseAll==0){
      is_chooseAll=1;
      for(var i=0;i<cartData.cart_goods.length;i++){
        cartData.cart_goods[i].flag=1;
      }
      chooseGoods=cartData.cart_goods;
    }
    
    // 当前是全选状态 点击取消所有选择 ——————— 要把状态修改为不全选且chooseGoods为空数组
    else{
      is_chooseAll=0;
      for (var i = 0; i < cartData.cart_goods.length; i++) {
        cartData.cart_goods[i].flag = 0;
      }
      chooseGoods=[];
    }
    this.setData({
      cartData:cartData,
      chooseGoods:chooseGoods,
      is_chooseAll:is_chooseAll
    })
    
    this.totalPrice();
  },

购物车的功能到这里就大概实现了。
欢迎各位大佬指正。

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