1. 程式人生 > >微信小程式實現購物車功能

微信小程式實現購物車功能

 在我的GitHub上有校園二手交易微信小程式的原始碼,這裡麵包含了購物車的功能,GitHub地址:https://github.com/zhuyuzhu/Secondhand-goods-on-campus,該專案的pages資料夾下的shoppingCart資料夾就是購物車的程式碼。

購物車功能實現的邏輯:

(1)從伺服器拿到的物品資料data裡面,只有物品的資訊,我們需要給每個物品資料中加入一個是否選中的屬性

這樣當我們在點選選擇按鈕的時候,就可以選中該物品,當再次點選的時候,就可以取消選擇。

其中幾個主要的功能:

(1)物品請求資料,使用微信小程式request請求,POST方式得到伺服器傳來的物品資料。

每次請求要想後端傳入使用者id和物品id(物品id根據後端要求進行處理,我每次傳入請求到的物品中最後一個物品的id,後端會把這個id之後的5個值再傳給前端)才得到的物品資料,每一次請求要判斷還有沒有資料,有資料則請求成功,沒有資料就不請求。

(2)選中和取消選中單個物品

(3)選中或取消選中物品時,總價格要進行加減

每次觸發選擇事件,都會觸發計算總價的方法

(4)全選按鈕,實現物品的全選

當用戶通過單選選擇了所有物品時,“全選按鈕”會自動改變為選中樣式;當用戶通過“全選按鈕”選擇所有商品的時候,每個商品都應該是選中狀態。

(5)計算總價

任何一次觸發該函式,都會重新計算價格,將總價變為0,再進行選中項的價格累加,而不是在原總價上累加或減某一個商品的價格

wxml程式碼: 

<!--pages/shoppingCart/shoppingCart.wxml-->
<view class='box'>
  <view class='wrapper'>
    <view class="tab-content {{selectBook? 'select': 'noSelect'}}" bindtap='chooseBookCart'>書本</view>
    <view class="tab-content {{selectThing? 'select': 'noSelect'}}" bindtap='chooseThingCart'>物品</view>

  </view>
</view>
<!-- 書本 -->
<view class="cart-box" wx:if="{{selectBook}}">
  <!-- wx:for 渲染購物車列表 -->
  <view wx:for="{{carts}}" wx:key="{{carts}}" class='cart-goods'>
    <!-- wx:if 是否選擇顯示不同圖示 -->
 <view class='icon-wrapper' bindtap="selectList" data-index="{{index}}">
    <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red"  />
    <icon wx:else type="circle" class='cart-icon'  />
    </view>
    <view  class='cart-img'>
      <image class="cart-thumb" src="{{item.picture}}"></image>
      <view class='cart-message'>
        <text class='name'>書名:{{item.bname}}</text>
        <text class='author'>作者:{{item.author}}</text>
        <text class='press'>出版社:{{item.press}}</text>
        <text class='price'>價格:¥{{item.bprice}}</text>
      </view>
    </view>
    <!-- 點選商品圖片可跳轉到商品詳情 -->
    
    <!-- 刪除按鈕 -->
    <text bindtap="deleteList" data-index="{{index}}" class='delete'> × </text>
  </view>
  <view wx:if="{{isMyCartShow}}" class='bottom'>沒有書本啦~_~</view>
</view>
<!-- 物品 -->
<view class="cart-box" wx:if="{{selectThing}}">
  <!-- wx:for 渲染購物車列表 -->
  <view wx:for="{{thingCarts}}" wx:key="{{thingCarts}}" class='cart-goods'>
    <!-- wx:if 是否選擇顯示不同圖示 -->
     <view class='icon-wrapper' bindtap="selectListThing" data-index="{{index}}">
    <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red"  />
    <icon wx:else type="circle" class='cart-icon'  />
    </view>

    <view  class='cart-img'>
      <image class="cart-thumb" src="{{item.gpicture}}"></image>
      <view class='cart-message'>
        <text class="name">{{item.gname}}</text>
        <text class="author">校區:{{item.gcollege}}</text>
        <text class='author'>成色:{{item.gstatus}}</text>
        <text class='author'>釋出者:{{item.usersname}}</text>
        <text class='price'>¥{{item.gprice}}</text>
      </view>
    </view>
    <!-- 點選商品圖片可跳轉到商品詳情 -->
    
    <!-- 刪除按鈕 -->
    <text bindtap="deleteListThing" data-index="{{index}}" class='delete'> × </text>
  </view>
  <view wx:if="{{isThingCartShow}}" class='bottom'>沒有物品啦~_~</view>
</view>
<!-- 底部操作欄 -->
<view class='cart-bottom'>
  <!-- wx:if 是否全選顯示不同圖示 -->
  <icon wx:if="{{selectAllStatus}}" class='cart-iconAll' type="success_circle" color="red" bindtap="selectAll" />
  <icon wx:else type="circle" class='cart-iconAll' color="#ff7100" bindtap="selectAll" />
  <text class='cart-allSelect' bindtap="selectAll">全選</text>
  <!-- 總價 -->
  <text class='cart-allPrice'>合計:</text>
  <text class='allPrice'>¥{{totalPrice}}</text>
  <button class='btn-red' bindtap='toBuy' form-type='submit'>去結算</button>
</view>

 wxss程式碼:

/* pages/shoppingCart/shoppingCart.wxss */
.wrapper {
  position: fixed;
  top: 0rpx;
  display: flex;
  width: 100%;
  height: 50rpx;
  justify-content: space-around;
  background-color: #fff;
  z-index: 9999;
}
.select {
 
  text-align: center;
  width: 50%;
  background-color: green;
  color: #fff;
}
.noSelect {
  width: 50%;
  text-align: center;
}
.cart-box {
   margin-top: 50rpx;
  margin-bottom: 100rpx;
}
.cart-goods {
  display: flex;
  flex-direction: row;
  padding: 30rpx;
  border-bottom: 3rpx solid #e6e6e6;
}
.icon-wrapper {
  line-height: 260rpx;
}
 .cart-icon {
    display: inline-block;
    margin: auto 10rpx;
    margin-left: -10rpx;
  }
 .cart-img {
   display: flex;
  width: 580rpx;
  height: 260rpx;
}
.cart-img image{
  margin: auto 0rpx;
  width: 165rpx;
  height: 225rpx;
}
 .cart-goods .cart-message {
  width: 380rpx;
  display: flex;
  flex-direction: column;
  margin: 0 20rpx;
  justify-content: space-around;
  
}
 .name{
  font-weight: 600;
  color: #4a4a4a;
  font-size: 32rpx;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
 .author,
 .press{
    font-size: 28rpx;
    color: #9e9e9e;
    font-weight: 300;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden; 
  }
  .price {
    font-size: 28rpx;
    color: #f40;
    font-weight: 300;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden; 
  }
  .delete {
    position: absolute;
    right: 40rpx;
    margin-top: -10rpx;
  }
  .cart-bottom {
    position: fixed;
    width: 100%;
    height: 100rpx;
    background-color: white;
    bottom: 0rpx;
  }
  .cart-allPrice {
  float:left;
   padding: 0.5rem;
    font-weight: 100;
    margin-left: 70rpx;
  }
  .allPrice {
     float:left;
    padding: 0.5rem;
    font-weight: 100;
   margin-left: -30rpx;
   color: #f40;
  }
  .cart-allSelect {
    float:left;
    padding: 0.5rem;
    margin-left: -23rpx;
     font-weight: 100
  }
  .cart-iconAll {
    float:left;
    padding: 0.5rem;
   margin-top: 7rpx;
  }
  .btn-red {
  background-color: #f44336; /* 紅色 */
  font-size: 40rpx;
}
button {
  position: fixed;
  right: 0;
  color: white;
  text-align: center;
  display: inline-block;
  font-size: 30rpx;
  border-radius: 0rpx;
  width: 30%;
  height: 100rpx;
  line-height: 100rpx;
}
.cart-list {
  display: flex;
  flex-direction: column;
}
.bottom {
 
  color: #666;
  text-align: center;
  font-size: 30rpx;

}

微信js程式碼:

// pages/shoppingCart/shoppingCart.js
var app = getApp();
const orginalPrice = 0; //由於0.00在賦值時是0,用toFixed()取餘
Page({

  /**
   * 頁面的初始資料
   */
  data: {
    selectTab: true,
    selectBook: true,
    selectThing: false, 

    carts: [], // 購物車列表
    hasList: false, // 列表是否有資料
    totalPrice: orginalPrice.toFixed(2), // 總價,初始為0
    selectAllStatus: false, // 全選狀態,預設全選
    bookId: '',
    isMyCartShow: false,
    studentId: '', 
    myCartBookLength: '5',
    bookPrice: 0,

    thingId: '',
    thingCarts: [], // 物品列表
    isThingCartShow: false,
    myCartThingLength: '5',
    thingPrice: 0,
  },

  /**
   * 生命週期函式--監聽頁面載入
   */
  onLoad: function (options) {

    
  },

  /**
   * 生命週期函式--監聽頁面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命週期函式--監聽頁面顯示
   */
  onShow: function () {
    var that = this;
    var studentId = that.data.studentId;
    var hasList = that.data.hasList;
    try {
      var value = wx.getStorageSync('studentIdSync')
      if (value) {
        console.log(value); //同步得到studentId的值
        that.setData({
          studentId: value
        })
      }
    } catch (e) {
      console.log(0);
    }
    this.getBookCartList()
  },

  /**
   * 生命週期函式--監聽頁面隱藏
   */
  onHide: function () {

  },

  /**
   * 生命週期函式--監聽頁面解除安裝
   */
  onUnload: function () {

  },

  /**
   * 頁面相關事件處理函式--監聽使用者下拉動作
   */
  onPullDownRefresh: function () {
    // 動態設定導航條標題
    wx.setNavigationBarTitle({
      title: '購物車'
    });
    wx.showNavigationBarLoading(); //在標題欄中顯示載入圖示
    setTimeout(function(){
      wx.stopPullDownRefresh(); //停止載入
      wx.hideNavigationBarLoading(); //隱藏載入icon
    },2000)
  },

  /**
   * 頁面上拉觸底事件的處理函式
   */
  onReachBottom: function () {
    if (this.data.selectBook){
      this.getBookCartList()
    }else {
      this.getThingCartList()
    }
    
  },
getBookCartList(){
  console.log(1);
  var that = this;
  var url = app.globalData.huanbaoBase + 'getbooksbystudentid.php'
  var ismyCartShow = that.data.ismyCartShow;
  var carts = that.data.carts;
  var bookId = that.data.bookId;
  var myCartBookLength = that.data.myCartBookLength;
  var studentId = that.data.studentId;
  console.log(bookId, myCartBookLength);
  // if (myCartBookLength < 5) {
  //   that.setData({
  //     isMyCartShow: true
  //   })
  //   return
  // }
  wx.showToast({
    title: '載入中',
    icon: 'loading',
    duration: 1000,
  })
  
  wx.request({
    url,
    method: 'POST',
    header: { 'content-type': 'application/x-www-form-urlencoded ' },
    data: { //此處設定,一定要與後臺一一對應,屬性名和屬性的先後位置。
      studentId: studentId,
      lastId: bookId,
    },
    success: res => {
      var carts = that.data.carts || [];
      var data = res.data.data;  
      console.log(data);
      if(data === undefined) {
        wx.hideToast()
        that.setData({
          isMyCartShow: true
        })
        return 
      }
      that.setData({
        myCartBookLength: data.length  //每次獲取5組值
      })
      myCartBookLength = data.length; 
      that.setData({
        bookId: res.data.data[myCartBookLength - 1].bookid
      })
      console.log(myCartBookLength);
      data.forEach(item => {
          let messege = {
          selected: false,
          ...item
        }
        carts.push(messege); //實現購物車的最近新增的物品,展現在最前面
      })

      that.setData({
        carts:  carts ,
      })
     
    },
    fail: err => {
      console.log(err);
    }
  })
},
  getThingCartList() {
    console.log(1);
    var that = this;
    var url = app.globalData.huanbaoBase + 'getthingsbystudentid.php'
    var isThingCartShow = that.data.isThingCartShow;
    var thingCarts = that.data.thingCarts;
    var thingId = that.data.thingId;
    var myCartThingLength = that.data.myCartThingLength;
    var studentId = that.data.studentId;
    var selectBook = that.data.selectBook;
    var selectThing = that.data.selectThing;
    
    console.log(thingId, myCartThingLength);
    // if (myCartThingLength < 5) {
    //   that.setData({
    //     isThingCartShow: true
    //   })
    //   return
    // }
    wx.showToast({
      title: '載入中',
      icon: 'loading',
      duration: 1000,
    })

    wx.request({
      url,
      method: 'POST',
      header: { 'content-type': 'application/x-www-form-urlencoded ' },
      data: { //此處設定,一定要與後臺一一對應,屬性名和屬性的先後位置。
        studentId: studentId,
        lastId: thingId,
       },
      success: res => {
        var thingCarts = that.data.thingCarts || [];
        var data = res.data.data;
        console.log(data);
        if (data === undefined) {
          wx.hideToast()
          that.setData({
            isThingCartShow: true
          })
          return
        }
        that.setData({
          myCartThingLength: data.length  //每次獲取5組值
        })
        myCartThingLength = data.length;
        that.setData({
          thingId: res.data.data[myCartThingLength - 1].goodid
        })
        console.log(myCartThingLength);
        data.forEach(item => {
          let messege = {
            selected: false,
            ...item
          }
          thingCarts.push(messege); //實現購物車的最近新增的物品,展現在最前面
        })

        that.setData({
          thingCarts: thingCarts,
        })

      },
      fail: err => {
        console.log(err);
      }
    })
  },
  /**
   * 使用者點選右上角分享
   */
  onShareAppMessage: function () {

  },
  //計量總價
  getTotalPrice() {
    let carts = this.data.carts; // 獲取購物車列表
    let thingPrice = parseFloat(this.data.thingPrice);
    let bookPrice = parseFloat(this.data.bookPrice);
    let total = 0.00;
    for (let i = 0; i < carts.length; i++) { // 迴圈列表得到每個資料
      if (carts[i].selected) { // 判斷選中才會計算價格
       
        total += parseFloat(carts[i].bprice); // 所有價格加起來
      }
    }
    this.setData({
      bookPrice: total.toFixed(2)
    })
    total += thingPrice;
    this.setData({ // 最後賦值到data中渲染到頁面
      carts: carts, 
      totalPrice: total.toFixed(2) //保留小數後面2兩位
    });
  },
  //選擇事件
  selectList(e) {
    let that = this;
    const index = e.currentTarget.dataset.index;    // 獲取data- 傳進來的index
    console.log(index);
  
    let selectAllStatus = that.data.selectAllStatus; //是否已經全選
    let str = true;  //用str與每一項進行狀態判斷
    let carts = that.data.carts;                    // 獲取購物車列表
    const selected = carts[index].selected;         // 獲取當前商品的選中狀態
    carts[index].selected = !selected;              // 改變狀態
    that.setData({
      carts: carts
    });
    that.getTotalPrice();                           // 重新獲取總價
    for (var i = 0; i < carts.length; i++) {
      str = str && carts[i].selected;           //用str與每一項進行狀態判斷
    }
  
    if (str === true) {
      that.setData({
        selectAllStatus: true
      })
    } else {
      that.setData({
        selectAllStatus: false
      })
    }
  },
  //全選事件
  selectAll(e) {
    var that = this;
    let selectAllStatus = that.data.selectAllStatus;    // 是否全選狀態
    let carts = that.data.carts;
    let thingCarts = that.data.thingCarts;
    var selectThing = that.data.selectThing;
    var selectBook = that.data.selectBook;
  if(selectBook) {
    selectAllStatus = !selectAllStatus;
    for (let i = 0; i < carts.length; i++) {
      carts[i].selected = selectAllStatus;            // 改變所有商品狀態
    }
    that.setData({
      selectAllStatus: selectAllStatus,
      carts: carts
    });
    that.getTotalPrice();                               // 重新獲取總價
    if (carts.length === 0) { //當沒有物品時,不能再點“全選”
      wx.showModal({
        title: '提示',
        content: '購物車空空如也~',
        success: function (res) {   //模糊層成功出來後
          if (res.confirm) {
            console.log('使用者點選確定')
            that.setData({
              selectAllStatus: false
            })
          } else {
            console.log('使用者點選取消')
            that.setData({
              selectAllStatus: false
            })
          }
        },
      })
    }
  }else {
    selectAllStatus = !selectAllStatus;
    for (let i = 0; i < thingCarts.length; i++) {
      thingCarts[i].selected = selectAllStatus;            // 改變所有商品狀態
    }
    that.setData({
      selectAllStatus: selectAllStatus,
      thingCarts: thingCarts
    });
    that.getTotalPriceThing();                               // 重新獲取總價
    if (thingCarts.length === 0) { //當沒有物品時,不能再點“全選”
      wx.showModal({
        title: '提示',
        content: '購物車空空如也~',
        success: function (res) {   //模糊層成功出來後
          if (res.confirm) {
            console.log('使用者點選確定')
            that.setData({
              selectAllStatus: false
            })
          } else {
            console.log('使用者點選取消')
            that.setData({
              selectAllStatus: false
            })
          }
        },

      })

    }
  }
  },

  //刪除商品
  deleteList(e) {
    const index = e.currentTarget.dataset.index;
    var selectAllStatus = this.data.selectAllStatus;
    let carts = this.data.carts;
    let totalPrice = this.data.totalPrice;
    wx.showModal({
      title: '提示',
      content: '將此產品移除購物車?',
      success: res=> {
        if (res.confirm) {
          console.log('使用者點選確定')
          carts.splice(index, 1);              // 刪除購物車列表裡這個商品
          this.setData({
            carts: carts
          });
          if (carts.length == 0) {                  // 如果購物車為空
            this.setData({
              hasList: false,             // 修改標識為false,顯示購物車為空頁面
              selectAllStatus: false,
              totalPrice: orginalPrice.toFixed(2)              //此時價格為0
            });
          } else {                              // 如果不為空
            this.getTotalPrice();           // 重新計算總價格
          }
        } else if (res.cancel) {
          console.log('使用者點選取消')
        }
      }
    })
  },

// 物品
  //計量總價
  getTotalPriceThing() {
    let thingCarts = this.data.thingCarts; // 獲取購物車列表
    let total = 0; //注意後臺返回的是字串數字。
    let thingPrice = parseFloat(this.data.thingPrice);
    let bookPrice = parseFloat(this.data.bookPrice);
    for (let i = 0; i < thingCarts.length; i++) { // 迴圈列表得到每個資料
      if (thingCarts[i].selected) { // 判斷選中才會計算價格  
        total += parseFloat(thingCarts[i].gprice); // 所有價格加起來  
      }
    }
    this.setData({
      thingPrice: total
    })
    total += bookPrice;
    this.setData({ // 最後賦值到data中渲染到頁面
      thingCarts: thingCarts,
      totalPrice: total.toFixed(2) //保留小數後面2兩位
    });
  },
  //選擇事件
  selectListThing(e) {
    let that = this;
    const index = e.currentTarget.dataset.index;    // 獲取data- 傳進來的index
    console.log(index);

    let selectAllStatus = that.data.selectAllStatus; //是否已經全選
    let str = true;  //用str與每一項進行狀態判斷
    let thingCarts = that.data.thingCarts;                    // 獲取購物車列表
    const selected = thingCarts[index].selected;         // 獲取當前商品的選中狀態
    thingCarts[index].selected = !selected;              // 改變狀態
    that.setData({
      thingCarts: thingCarts
    });
    that.getTotalPriceThing();                           // 重新獲取總價
    for (var i = 0; i < thingCarts.length; i++) {
      str = str && thingCarts[i].selected;           //用str與每一項進行狀態判斷
    }
    console.log(str);
    if (str === true) {
      that.setData({
        selectAllStatus: true
      })
    } else {
      that.setData({
        selectAllStatus: false
      })
    }
  },


  //刪除商品
  deleteListThing(e) {
    const index = e.currentTarget.dataset.index;
    var selectAllStatus = this.data.selectAllStatus
    let thingCarts = this.data.thingCarts;
    let totalPrice = this.data.totalPrice;
    wx.showModal({
      title: '提示',
      content: '將此產品移除購物車?',
      success: res=> {
        if(res.confirm){
          console.log("使用者點了確定")
          thingCarts.splice(index, 1);              // 刪除購物車列表裡這個商品
          this.setData({
            thingCarts: thingCarts
          });
          if (thingCarts.length == 0) {                  // 如果購物車為空
            this.setData({
              hasList: false,             // 修改標識為false,顯示購物車為空頁面
              selectAllStatus: false,
              totalPrice: orginalPrice.toFixed(2)              //此時價格為0
            });
          } else {                              // 如果不為空
            this.getTotalPrice();           // 重新計算總價格
          }
        }else if(res.cancel) {
          console.log("使用者點了取消")
        }
      }
    })
  },
  chooseBookCart() {
    var that = this;
    var selectBook = that.data.selectBook;
    var selectThing = that.data.selectThing;
    let selectAllStatus = that.data.selectAllStatus; //是否已經全選
    let str = true;  //用str與每一項進行狀態判斷
    let carts = that.data.carts;  
    for (var i = 0; i < carts.length; i++) {
      str = str && carts[i].selected;           //用str與每一項進行狀態判斷
    }
    console.log(str);
    that.setData({
      selectBook: true,
      selectThing: false, 
    })
   
  },
  chooseThingCart() {
    var that = this;
    var selectThing = that.data.selectThing;
    var selectBook = that.data.selectBook;
    var selectAllStatus = that.data.selectAllStatus;
    
    that.setData({
      selectBook: false,
      selectThing: true,
      
    })
    // 此時data中的資料改變,但是此時的屬性值還未改變
    
    that.getThingCartList()
    
  },
  toBuy(){
    var totalPrice = this.data.totalPrice;
    var thingCarts = this.data.thingCarts;
    var bookCarts = this.data.carts;
    var bookId = this.data.bookId;
    var bookCart = [], thingCart = [];
    bookCarts.forEach(item=>{
      if (item.selected){
        bookCart.push(item);
      }
    })
    thingCarts.forEach(item=>{
      if (item.selected){
        thingCart.push(item);
      }
    })
    let shoppingCartList = {thingCart, bookCart};
    
    console.log(bookCart);
    if(totalPrice === '0.00'){
     console.log(totalPrice);

    }else {
      console.log(shoppingCartList);
      wx.navigateTo({
        url: '../settlement/settlement?bookCart='+bookCart,
      })
    }

  }
})

後端程式碼和資料庫有時間再寫吧。。。