專案實戰-點餐小程式-23 點餐(購物車)
阿新 • • 發佈:2021-08-17
一、功能需求
- 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 })
三、效果展示