1. 程式人生 > 其它 >專案實戰-點餐小程式-23 點餐(購物車)

專案實戰-點餐小程式-23 點餐(購物車)

一、功能需求

  • 1、購物車固定顯示在點餐頁面底部
  • 2、實時統計購物車總數量和總金額
  • 3、已選菜品展示在購物車
  • 4、新增菜品到購物車(菜品列表增加和購物車內增加同步)
  • 5、減少菜品到購物車(菜品列表減少和購物車內減少同步)
  • 6、購物車蒙層的顯示和隱藏
  • 7、購物車列表載入快取菜品資訊、已點菜品總數量、總金額
  • 8、清空購物車

二、程式碼實現

1、food.wxml

 1 <!-- 搜尋 -->
 2 <view class="searchRoot">
 3 <input type="text" value="{{searchKey}}" class="searchInput"
placeholder="搜尋菜品" bindinput="getSearchContent" confirm-type="search" bindconfirm="searchFood"></input> 4 <image src="/images/search.png" class="searchIcon" bindtap="searchFood"></image> 5 </view> 6 7 <!-- 菜品列表 --> 8 <view class="hotFoodRoot"> 9 <view class
="hotFoodItem" wx:for="{{foodList}}"> 10 <image src="{{item.icon}}"></image> 11 <view class="hotFoodText"> 12 <view class="itemName">{{item.name}}</view> 13 <view class="itemSell">銷量:{{item.sell}}</view> 14 <view class="addAndMinusRoot"
> 15 <view class="itemPrice">{{item.price}}</view> 16 <!-- 菜品數量的加減 --> 17 <view class="addAndMinus"> 18 <image class="img" src="/images/minus.png" bindtap="minus" data-id="{{item._id}}"></image> 19 <text class="number">{{item.number}}</text> 20 <image class="img" src="/images/add.png" bindtap="add" data-id="{{item._id}}"></image> 21 </view> 22 </view> 23 </view> 24 </view> 25 </view> 26 <!-- 底部區域 --> 27 <view class="cartRoot"> 28 <view class="cartBackground"> 29 <image class="cartPackage" src="/images/package.png" bindtap="showCart"> 30 <view class="cartNumber"> 31 <text class="totalNumber">{{totalNumber}}</text> 32 </view> 33 </image> 34 <text class="totalMoney">{{totalMoney}}</text> 35 </view> 36 <view class="payMoney">選好了</view> 37 </view> 38 <!-- 購物車蒙層 --> 39 <view class="maskBackground" hidden="{{isHideMask}}"> 40 </view> 41 <!-- 購物車列表 --> 42 <view class="cartDetail" hidden="{{isHideMask}}"> 43 <!-- 標題 --> 44 <view class="cartTitle"> 45 <text class="foodTitle" bindtap="hideCart">返回</text> 46 <view class="delete" bindtap="clearCart"> 47 <image src="/images/delete.png"></image> 48 <text>清空</text> 49 </view> 50 </view> 51 <!-- 資料 --> 52 <scroll-view class="cartData"> 53 <view wx:for="{{cartList}}" class="cartItem"> 54 <image src="{{item.icon}}" class="cartImg"></image> 55 <view class="cartText"> 56 <view class="cartName">{{item.name}}</view> 57 <view class="cartMsg"> 58 <view class="cartPrice">{{item.price}}</view> 59 <!-- 菜品數量的加減 --> 60 <view class="addMinus"> 61 <image class="img" src="/images/minus.png" bindtap="minus" data-id="{{item._id}}"></image> 62 <text class="number">{{item.number}}</text> 63 <image class="img" src="/images/add.png" bindtap="add" data-id="{{item._id}}"></image> 64 </view> 65 </view> 66 </view> 67 </view> 68 </scroll-view> 69 </view>

2、food.wxss

  1 /*搜尋*/
  2 .searchRoot{
  3   display: flex;
  4   flex-direction: row;
  5   /*彈性盒內各項元素沿著主軸居中顯示*/
  6   align-items: center;
  7   padding: 20rpx;
  8 }
  9 .searchInput{
 10   border: 1rpx solid #FF9966;
 11   border-radius: 20rpx;
 12   padding: 0 30rpx;
 13   flex: 1;
 14   height: 76rpx;
 15 }
 16 .searchIcon{
 17   width: 60rpx;
 18   height: 60rpx;
 19   margin-left: 20rpx;
 20 }
 21 /*菜品資料*/
 22 .hotFoodRoot{
 23   /*設定下內邊距,防止固定的購物車擋住最後一個菜品*/
 24   padding-bottom: 140rpx;
 25 }
 26 .hotFoodItem{
 27   display: flex;
 28   margin: 20rpx 20rpx 0 20rpx;
 29   border-bottom: 1rpx solid rgb(245, 245, 245);
 30 }
 31 .hotFoodItem image{
 32   width: 120rpx;
 33   height: 120rpx;
 34   margin-right: 20rpx;
 35   border-radius: 10rpx;
 36   /*防止標題過長把圖片擠走*/
 37   min-width: 120rpx;
 38 }
 39 
 40 .hotFoodItem .itemName{
 41   font-size: 32rpx;
 42   /*設定菜品名稱超過一行時顯示省略號*/
 43   width: 500rpx;
 44   white-space: nowrap;
 45   text-overflow: ellipsis;
 46   overflow: hidden;
 47 }
 48 .hotFoodItem .itemSell{
 49   font-size: 28rpx;
 50   color: gray;
 51 }
 52 
 53 /*數量加減*/
 54 .addAndMinusRoot{
 55   display: flex;
 56   justify-content: space-between;
 57   align-items: center;
 58 }
 59 .addAndMinusRoot .itemPrice{
 60   font-size: 30rpx;
 61   color: #FF9966;
 62 }
 63 .addAndMinusRoot .itemPrice::before{
 64   /*人民幣符號*/
 65   content: "¥";
 66   color:#FF9966;
 67 }
 68 .addAndMinusRoot .addAndMinus{
 69   display: flex;
 70   justify-content: flex-end;
 71   align-items: center;
 72 }
 73 .addAndMinus .img{
 74   margin: 0;
 75   width: 50rpx;
 76   /*必須加上min-width*/
 77   min-width: 50rpx;
 78   height: 50rpx;
 79 }
 80 .addAndMinus .number{
 81   margin: 0 20rpx;
 82 }
 83 /*底部區域*/
 84 .cartRoot{
 85   width: 100%;
 86   display: flex;
 87   justify-content: center;
 88   /*固定在底部*/
 89   position: fixed;
 90   bottom: 20rpx;
 91   z-index: 201;
 92 }
 93 .cartBackground{
 94   width: 450rpx;
 95   height: 100rpx;
 96   background-color:#fff;
 97   border-top-left-radius: 50rpx;
 98   border-bottom-left-radius: 50rpx;
 99   box-shadow:  0 0 5px gainsboro;
100   display:flex;
101   justify-content: flex-start;
102   align-items: center;
103 }
104 .cartPackage{
105   width: 80rpx;
106   height: 80rpx;
107   margin: 0 30rpx;
108   position: relative;
109 }
110 .cartNumber{
111   width: 40rpx;
112   height: 40rpx;
113   border-radius: 50%;
114   background-color:red;
115   position: absolute;
116   top: 0;
117   right: 0;
118   display: flex;
119   align-items: center;
120   justify-content: center;
121 }
122 .totalNumber{
123   font-size: 24rpx;
124   color: #fff;
125   line-height: 30rpx;
126 }
127 .totalMoney{
128   font-size: 30rpx;
129   color: #ff9966;
130 }
131 .totalMoney::before{
132   content: '¥';
133   font-size: 20rpx;
134   color: #ff9966;
135 }
136 /*去結算*/
137 .payMoney{
138   width: 200rpx;
139   height: 100rpx;
140   background-color:#FF9966;
141   border-top-right-radius: 50rpx;
142   border-bottom-right-radius: 50rpx;
143   box-shadow:  0 0 5px gainsboro;
144   text-align: center;
145   line-height: 100rpx;
146   color: #fff;
147 }
148 /*購物車蒙層*/
149 .maskBackground{
150     position: fixed;
151     top: 0;
152     right: 0;
153     bottom: 0;
154     left: 0;
155     background-color: gray;
156     /*設定背景顏色透明度*/
157     opacity: .4;
158     /*設定層級*/
159     z-index: 100;
160 }
161 
162 /*購物車詳情*/
163 .cartDetail{
164   position: fixed;
165   bottom: 0;
166   left: 0;
167   right: 0;
168   height: 600rpx;
169   background-color: #fff;
170   border-top-left-radius: 20rpx;
171   border-top-right-radius: 20rpx;
172   z-index: 200;
173   /*解決滑動衝突的問題*/
174   overflow: auto;
175   /*底部內邊距,為購物車預留空間*/
176   padding-bottom: 140rpx;
177 }
178 /*購物車標題*/
179 .cartTitle{
180   width: 100%;
181   display: flex;
182   justify-content: space-between;
183   align-items: center;
184   border-bottom: 1rpx solid #f2f2f2;
185   border-top-left-radius: 20rpx;
186   border-top-right-radius: 20rpx;
187   background-color: #fff;
188   height: 80rpx;
189   z-index: 201;
190   /*固定購物車標題*/
191   position: fixed;
192   left: 0;
193   right: 0;
194 }
195 .cartTitle .foodTitle{
196   font-size: 28rpx;
197   margin-left: 20rpx;
198   color: #FF9966;
199 }
200 .cartTitle .delete{
201   display: flex;
202   align-items: center;
203   margin: 20rpx;
204 }
205 .delete image{
206   width: 40rpx;
207   height: 40rpx;
208   margin-right: 5rpx;
209 }
210 .delete text{
211   font-size: 28rpx;
212   color: #c3c3c3;
213 }
214 /*購物車資料*/
215 .cartData{
216   margin-top: 80rpx;
217 }
218 .cartItem{
219   display: flex;
220   margin: 20rpx 20rpx 0 20rpx;
221   border-bottom: 1rpx solid rgb(245, 245, 245);
222 }
223 .cartItem .cartImg{
224   width: 100rpx;
225   height: 100rpx;
226   border-radius: 10rpx;
227   margin-right: 20rpx;
228   /*防止標題過長把圖片擠走*/
229   min-width: 100rpx;
230 }
231 .cartText{
232   display: flex;
233   flex-direction: column;
234   justify-content:space-around;
235 }
236 .cartItem .cartName{
237   font-size: 32rpx;
238   /*設定菜品名稱超過一行時顯示省略號*/
239   width: 500rpx;
240   white-space: nowrap;
241   text-overflow: ellipsis;
242   overflow: hidden;
243 }
244 
245 /*數量加減*/
246 .cartMsg{
247   display: flex;
248   justify-content: space-between;
249   align-items: center;
250 }
251 .cartPrice{
252   font-size: 30rpx;
253   color: #FF9966;
254 }
255 .cartPrice::before{
256   /*人民幣符號*/
257   content: "¥";
258   color:#FF9966;
259 }
260 .cartMsg .addMinus{
261   display: flex;
262   justify-content: flex-end;
263   align-items: center;
264 }
265 .addMinus .img{
266   margin: 0;
267   width: 50rpx;
268   /*必須加上min-width*/
269   min-width: 50rpx;
270   height: 50rpx;
271 }
272 .addMinus .number{
273   margin: 0 20rpx;
274 }

3、food.js

  1   //定義db
  2   const db = wx.cloud.database()
  3   //搜尋的菜品資訊
  4   let foodList = ''
  5   //首頁傳遞過來的使用者輸入的搜尋關鍵詞
  6   let searchKey = ''
  7 
  8 Page({
  9   //頁面的初始資料
 10   data: {
 11     //搜尋內容
 12     searchKey:'',
 13     //搜尋到的菜品資料
 14     foodList:[],
 15     //購物車的總數量、總金額、菜品資訊
 16     totalNumber:0,
 17     totalMoney:0,
 18     cartList:[],
 19     //購物車蒙版是否隱藏
 20     isHideMask:true
 21   },
 22 
 23   //生命週期函式--監聽頁面載入
 24   onLoad: function (options) {
 25     //從首頁攜帶搜尋詞
 26     console.log("從首頁攜帶過來的搜尋內容",options.searchKey);
 27     searchKey = options.searchKey
 28     //如果使用者輸入關鍵詞搜尋
 29     if(searchKey&&searchKey.length>0){  
 30       this.setData({
 31         searchKey:searchKey
 32       })
 33     }else{    //如果使用者不輸入關鍵詞搜尋,則搜尋所有菜品
 34       searchKey = ''
 35     }
 36     //獲取購物車快取資料(如果有快取,則取快取資料;如果無快取,則為空陣列)
 37     let cart = wx.getStorageSync('cart') || []
 38     //將購物車快取資訊渲染到頁面上
 39     this.setData({
 40       cartList:cart
 41     })
 42     //呼叫自定義方法,執行搜尋功能
 43     this.searchFood();
 44   },
 45 
 46   //獲取使用者輸入的搜尋內容
 47   getSearchContent(e){
 48     console.log("使用者輸入的搜尋內容",e.detail.value);
 49     searchKey = e.detail.value
 50   },
 51 
 52   //點選搜尋按鈕實現功能
 53   searchFood(){
 54     console.log("使用者點選了搜尋按鈕,輸入的關鍵詞為",searchKey);
 55     //購物車菜品資訊
 56     let cartList = this.data.cartList
 57       //使用正則查詢
 58       db.collection("food").where({
 59         name:db.RegExp({
 60           regexp:searchKey, //搜尋池
 61           options:'i' //不區分大小寫
 62         })
 63       }).get()
 64       .then(res=>{
 65         console.log("搜尋成功",res);
 66         foodList = res.data
 67         if(foodList&&foodList.length>0){
 68           foodList.forEach(item=>{
 69             //遍歷陣列foodList,為陣列新增新欄位number,賦值為0
 70             item.number = 0
 71             if(cartList&&cartList.length>0){
 72               //檢查當前購物車裡是否存在當前所選的菜品
 73               var res = cartList.find(cart=>{
 74                 return cart._id == item._id
 75               })
 76               if(res){
 77                 item.number = res.number
 78               }else{
 79                 item.number = 0
 80               }
 81             }
 82           })
 83           this.setData({
 84             foodList:foodList,
 85           })
 86           //呼叫自定義方法,計算購物車總數量和總價格
 87           this.getTotal()
 88         }
 89       }).catch(err=>{
 90         console.log("搜尋失敗",err);
 91       })
 92   },
 93 
 94   //點選增加菜品數量
 95   add(e){
 96     console.log("點選了加",e.currentTarget.dataset.id);
 97     let id = e.currentTarget.dataset.id
 98     //購物車菜品資訊
 99     let cartList = this.data.cartList
100     //遍歷當前菜品陣列
101     foodList.forEach(item=>{
102       if(item._id==id){
103         item.number+=1
104         //購物車所選菜品的資訊
105         if(cartList&&cartList.length>0){  //如果購物車中有資料
106         //檢查當前購物車裡是否存在當前所選的菜品
107          var res = cartList.find(cart=>{
108            return cart._id == id
109          })
110          console.log("當前所選的菜品是否存在於購物車裡",res);
111          console.log("+++以後購物車的菜品列表",cartList);
112          //如果所選的菜品不在購物車裡,直接新增到陣列
113          if(!res){
114           cartList.push(item)
115          }else{
116            res.number = item.number
117          }
118         }else{  //如果購物車中無資料,直接push到陣列
119           cartList.push(item)
120         }
121       }
122     })
123     console.log("遍歷以後的當前菜品列表",foodList);
124     console.log("新增到購物車的菜品列表",cartList);
125     this.setData({
126       //點選新增之後的菜品列表資訊
127       foodList:foodList,
128       //購物車所選商品列表
129       cartList:cartList
130     })
131     //呼叫自定義方法,計算購物車總數量和總價格
132     this.getTotal()
133     //將資料存入快取
134     wx.setStorageSync('cart', cartList)
135   },
136 
137   //點選減少菜品數量
138   minus(e){
139     console.log("點選了減",e.currentTarget.dataset.id);
140     let id = e.currentTarget.dataset.id
141     //購物車菜品資訊
142     let cartList = this.data.cartList    
143     //遍歷當前菜品陣列
144     foodList.forEach(item=>{
145       if(item._id==id){
146         if(item.number>0){
147           item.number-=1
148           //購物車所選菜品的資訊
149           if(cartList&&cartList.length>0){  //如果購物車中存在已選菜品
150           //查詢當前購物車裡是否存在當前所選的菜品
151           var index = cartList.findIndex(cart=>{
152             return cart._id == id
153           })
154           if(index>-1){
155             cartList[index].number = item.number
156           }
157           if(item.number == 0){
158             cartList.splice(index,1)  //刪除下標為index的1個元素
159           }
160         }
161         }else{
162           wx.showToast({
163             title: '數量不能小於0',
164             icon:'none'
165           })
166         }
167       }
168     })
169     console.log("遍歷以後的當前菜品列表",foodList);
170     console.log("---以後購物車的菜品列表",cartList);
171     this.setData({
172       foodList:foodList,
173       //購物車所選商品列表
174       cartList:cartList
175     })
176     //呼叫自定義方法,計算購物車總數量和總價格
177     this.getTotal()
178     //將資料存入快取
179     wx.setStorageSync('cart', cartList)
180   },
181 
182   //自定義,計算購物車的總價格和總數量
183   getTotal(){
184     //購物車的總數量、總金額、購物車菜品資訊
185     let totalNumber = 0
186     let totalMoney = 0
187     let cartList = this.data.cartList   
188     cartList.forEach(item=>{
189       totalNumber+=item.number
190       totalMoney+=item.number*item.price
191     })
192     this.setData({
193       totalNumber:totalNumber,
194       totalMoney:totalMoney
195     })
196   },
197 
198   //開啟購物車蒙層
199   showCart(){
200     this.setData({
201       isHideMask:false
202     })   
203   },
204   //關閉購物車蒙層
205   hideCart(){
206     this.setData({
207       isHideMask:true
208     })
209   },
210   
211   //清空購物車
212   clearCart(){
213     //把菜品列表所有菜品的數量置於0
214     let foodList = this.data.foodList //把菜品資料取出來
215     foodList.forEach(item=>{          //遍歷陣列,把每個數量設為0
216       item.number =0
217     })
218     //把購物車陣列設為空陣列
219     this.setData({
220       foodList:foodList,
221       cartList:[],
222       totalNumber:0,
223       totalMoney:0
224     })
225     //清空購物車快取資料
226     wx.setStorageSync('cart', null)
227   },
228 })

三、效果展示