項目實戰-點餐小程序-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 })

三、效果展示

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM