小程序外卖订单界面的示例代码
程序员文章站
2022-03-08 14:13:33
1.效果界面
2.涉及功能
*左侧商品类型、右侧商品可以相互控制;
*商品列表加减及购物车商品加减icon消失、显示;
*商品每一次加减,页面视...
1.效果界面
2.涉及功能
*左侧商品类型、右侧商品可以相互控制;
*商品列表加减及购物车商品加减icon消失、显示;
*商品每一次加减,页面视图变化(数量、价格变化、购物车置灰);
3.贴上所有代码
1.wxml
<view class="container"> <view class="index-cont"> <!-- 左边类型 --> <view class="index-left"> <view wx:for="{{foodslist}}" wx:key="index" class="item {{curid === 'item'+index?'on':''}}" data-id="item{{index}}" bindtap="scrolltoviewfn">{{item.name}}</view> </view> <!-- 右边产品 --> <scroll-view class="index-right" scroll-y="{{true}}" scroll-into-view="{{initview}}" scroll-with-animation="true" bindscroll="onpagescroll"> <view class="boxs"> <block wx:for="{{foodslist}}" wx:key="index"> <view class="index-title" id="item{{index}}">{{item.name}}</view> <view class="item" wx:for="{{item.list}}" wx:key="ind" wx:for-item="itm" wx:for-index="ind" bindtap="showgooddetail(itm)"> <view class="pic"><image src="{{itm.pic}}" mode="aspectfill"></image></view> <view class="main"> <view class="tit">{{itm.title}}</view> <view class="desc">{{itm.info}}</view> <view class="money">¥{{itm.price}}</view> </view> <view class="box"> <view wx:if="{{itm.num !== 0}}" class="icon" catchtap="reducenum(index, ind, itm)"><image src="../../../static/images/reduce-icon.png" alt=""></image></view> <input wx:if="{{itm.num !== 0}}" type="text" disabled wx:model="{{itm.num}}"/> <view class="icon" catchtap="addnum(index, ind, itm)"><image src="../../../static/images/add-icon.png" alt=""></image></view> </view> </view> </block> </view> </scroll-view> </view> <view class="index-cart"> <view class="left"> <view class="cart-num" wx:if="{{cartlist.length === 0}}"> <image src="../../../static/images/cart.png"></image> </view> <view class="cart-num on" wx:else bindtap="showcartmask"> <image src="../../../static/images/cart.png"></image> <text>{{totalnum}}</text> </view> <view class="cart-money">¥{{totalmoney}}</view> </view> <view class="order-btn" bindtap="submitorder">去结算</view> </view> <!--购物车弹窗--> <view class="dialog" wx:if="{{isshowcartmask && cartlist.length !== 0}}" bindtap="hiddencartmak()"> <view class="boxs" catchtap="stopmaopao()"> <view class="title-block"> <text>已选商品</text> <view class="clear" bindtap="clearcart"><image src="../../../static/images/del.png"></image>清空</view> </view> <scroll-view class="content" scroll-y="{{true}}" scroll-with-animation="true"> <block wx:for="{{cartlist}}" wx:key="index"> <view class="item" id="{{item.view}}"> <view class="tit">{{item.name}}</view> <view class="right"> <text>¥{{item.price}}</text> <view class="box"> <view class="icon" bindtap="reducecart(index, item)"><image src="../../../static/images/reduce-icon.png" alt=""></image></view> <input type="text" disabled wx:model="{{item.num}}"/> <view class="icon" bindtap="addcart(index, item)"><image src="../../../static/images/add-icon.png" alt=""></image></view> </view> </view> </view> </block> </scroll-view> </view> </view> <!--商品详情弹窗--> <view class="dialog1" wx:if="{{isshowdetail}}"> <scroll-view class="detbox" scroll-y="{{true}}" scroll-with-animation="true"> <image class="img" src="{{gooddetail.pic}}" mode="aspectfit"></image> <view class="box"> <view class="tit">{{gooddetail.title}}</view> <view class="money">¥{{gooddetail.price}}</view> <view class="desc">{{gooddetail.info}}</view> </view> <view class="close" bindtap="hidedetail"><image src="../../../static/images/close_ico.png"></image></view> </scroll-view> </view> </view>
2.script
createpage({ data: { foodslist: [], // 商品数据 cartlist: [], // 购物车数据 isshowcartmask: false, totalnum: 0, totalmoney: 0, initview: 'item0', // 根据此变量的变化,控制左侧选中状态、右侧滑动 curid: 'item0', isshowdetail: false, gooddetail: {}, screenwidth: 0, // 手机屏幕宽度 heightarray: [0] // 右侧每一个类型的高度区间数组 }, onload() { this.getgoodsdata() }, methods: { async getgoodsdata() { const that = this const res = await getgoodsinfo({}) this.foodslist = res wx.getsysteminfo({ success: (ress) => { that.screenwidth = ress.windowwidth } }) this.getheightsection() }, // 设置高度区间 所有单位转化为rpx getheightsection() { const that = this let hg = 0 for (let index = 0; index < that.foodslist.length - 1; index++) { hg += 70 + that.foodslist[index].list.length * 212 that.heightarray.push(hg) } }, // 获取高度区间的下标 getheightindex(arr, hg) { const that = this arr.foreach((item, index) => { if (hg >= item) { that.setdata({ curid: 'item' + index }) } }) }, // 左边菜单控制右边 scrolltoviewfn(e) { this.setdata({ initview: e.target.dataset.id, curid: e.target.dataset.id }) }, // 右边滚动控制左边 onpagescroll(e) { const that = this let scrolltop = e.detail.scrolltop * 750 / that.screenwidth this.getheightindex(that.heightarray, scrolltop) }, // 商品列表的减号点击 reducenum(index, ind, item) { const that = this let val = 'foodslist[' + index + '].list[' + ind + '].num' this.setdata({ [val]: item.num - 1 }) // 如果商品为0,就把当前商品在购物车清除 // 如果不为0, 就将当前商品数量减1 if (that.foodslist[index].list[ind].num === 0) { that.removeaarry(that.cartlist, item.id) } else { that.cartlist.foreach((itm, i) => { if (itm.id === item.id) { let value = 'cartlist[' + i + '].num' that.setdata({ [value]: itm.num - 1 }) } }) } this.computed() }, // 商品列表的加号点击 addnum(index, ind, item) { const that = this let val = 'foodslist[' + index + '].list[' + ind + '].num' this.setdata({ [val]: item.num + 1 }) // 如果商品为1,就把当前商品加入购物车 // 否则, 就将当前商品数量加1 if (that.foodslist[index].list[ind].num === 1) { let val = { id: item.id, name: item.title, price: item.price, num: 1, index: index, ind: ind, pic: item.pic } that.cartlist.push(val) } else { that.cartlist.foreach((itm, i) => { if (itm.id === item.id) { let value = 'cartlist[' + i + '].num' that.setdata({ [value]: itm.num + 1 }) } }) } this.computed() }, // 购物车的减号点击 reducecart(index, item) { const that = this let val = 'foodslist[' + item.index + '].list[' + item.ind + '].num' let val1 = 'cartlist[' + index + '].num' this.setdata({ [val]: item.num - 1, [val1]: item.num - 1 }) // 如果商品为0,就把当前商品在购物车清除 // 如果不为0, 就将当前商品数量减1 if (that.cartlist[index].num === 0) { that.removeaarry(that.cartlist, item.id) } this.computed() }, // 购物车的加号点击 addcart(index, item) { const that = this let val = 'cartlist[' + index + '].num' that.setdata({ [val]: item.num + 1 }) this.computed() }, // 清空购物车 clearcart() { const that = this wx.showmodal({ title: '提示', content: '清空购物车?', success: function (res) { if (res.confirm) { that.setdata({ cartlist: [] }) that.foodslist.foreach((item, i) => { item.list.foreach((itm, j) => { let value = 'foodslist[' + i + '].list[' + j + '].num' that.setdata({ [value]: 0 }) }) }) that.computed() } } }) }, // 计算选择商品总价格和总数量 computed() { const that = this let num = 0 let money = 0 that.cartlist.foreach(item => { num += item.num money += parsefloat(item.price) * item.num }) that.setdata({ totalnum: num, totalmoney: money }) }, // 将数量为0的时候,对应商品在购物车中删除 removeaarry(arr, id) { arr.foreach((item, index) => { if (item.id === id) { arr.splice(index, 1) } }) return arr }, showcartmask() { this.isshowcartmask = !this.isshowcartmask }, hiddencartmak() { this.isshowcartmask = false }, stopmaopao() { }, showgooddetail(item) { this.gooddetail = item this.isshowdetail = true }, hidedetail() { this.isshowdetail = false }, // 订单提交 submitorder() { } } })
3.css
<style lang='scss'> @import '../../style/base.scss'; page { height: 100%; } .container { height: 100vh; background-color: #fff; box-sizing: border-box; overflow: hidden; .dialog1{ width: 100%; height: 100vh; position: fixed; top: 0; left: 0; background-color: rgba(0,0,0, 0.5); z-index: 4; .detbox{ position: fixed; bottom: 0; left: 0; right: 0; background-color: #fff; width: 100%; max-height: 700rpx; overflow-y: auto; color: #333; border-radius: 40rpx 40rpx 0 0; .img{ width: 100%; height: 375rpx; background: rgba(0,0,0,0.6); } .box{ padding: 20rpx 30rpx 40rpx; box-sizing: border-box; .tit{ font-size: 28rpx; color: #333; font-weight: bold; } .money{ font-size: 26rpx; color: #f00; margin: 10rpx 0; } .desc{ font-size: 22rpx; color: #666; line-height: 32rpx; } } .close{ width: 50rpx; height: 50rpx; position: absolute; right: 20rpx; top: 20rpx; display: flex; align-items: center; justify-content: center; image{ width: 40rpx; height: 40rpx; } } } } .dialog{ width: 100%; height: 100vh; position: fixed; top: 0; left: 0; background-color: rgba(0,0,0, 0.5); z-index: 2; .boxs{ position: fixed; bottom: 80rpx; left: 0; right: 0; z-index: 6; background-color: #fff; width: 100%; max-height: 600rpx; color: #333; .title-block{ padding: 0 30rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; height: 70rpx; background: #eef0f1; text{ font-size: 26rpx; color: #666; } .clear{ font-size: 22rpx; color: #888; display: flex; align-items: center; image{ width: 24rpx; height: 24rpx; margin-right: 10rpx; } } } .content{ width: 100%; max-height: 530rpx; overflow-y: auto; padding-bottom: 30rpx; box-sizing: border-box; .item{ width: 690rpx; height: 80rpx; line-height: 80rpx; margin: 0 auto; position: relative; display: flex; align-items: center; justify-content: space-between; &::after{ position: absolute; width: 100%; height: 1rpx; background: #f2f2f2; content: ''; bottom: 1rpx; left: 0; } .tit{ width: 400rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 28rpx; color: #333; } .right{ display: flex; justify-content: flex-start; align-items: center; height: 80rpx; text{ font-size: 26rpx; color: #f00; } .box{ display: flex; justify-content: flex-start; align-items: center; flex-wrap: nowrap; margin-left: 20rpx; height: 80rpx; .icon{ width: 34rpx; height: 34rpx; display: flex; align-items: center; justify-content: center; image{ width: 34rpx; height: 34rpx; } } input{ width: 60rpx; height: 34rpx; border: none; color: #333; text-align: center; font-size: 26rpx; } } } } } } } .index-cont{ height: calc(100vh - 80rpx); display: flex; justify-content: space-between; .index-left{ width: 160rpx; height: 100%; background: #efefef; .item{ font-size: 26rpx; color: #333; border-bottom: 1rpx dashed #666; height: 80rpx; line-height: 80rpx; padding: 0 20rpx; box-sizing: border-box; &.on{ background: #fff; } } } .index-right{ width: 590rpx; height: 100%; .boxs{ padding: 0 30rpx; box-sizing: border-box; width: 100%; } .index-title{ height: 70rpx; line-height: 70rpx; background: #f7f7f7; padding-left: 30rpx; font-size: 26rpx; color: #666; box-sizing: border-box; } .item{ padding: 30rpx 0; box-sizing: border-box; display: flex; justify-content: space-between; position: relative; height: 212rpx; &::after{ position: absolute; top: 0rpx; left: 0; background: #ccc; width: 100%; height: 1rpx; content: ''; } .pic{ width: 150rpx; height: 150rpx; image{ width: 100%; height: 100%; } } .main{ width: 380rpx; padding-left: 30rpx; box-sizing: border-box; .tit{ font-size: 26rpx; color: #333; font-weight: bold; } .desc{ font-size: 22rpx; color: #999; line-height: 30rpx; margin: 5rpx 0 10rpx; min-height: 65rpx; } .money{ font-size: 28rpx; color: #f00; } } .box{ display: flex; justify-content: flex-start; align-items: center; flex-wrap: nowrap; margin-left: 10rpx; height: 34rpx; position: absolute; right: 0; bottom: 30rpx; .icon{ width: 34rpx; height: 34rpx; display: flex; align-items: center; justify-content: center; image{ width: 34rpx; height: 34rpx; } } input{ width: 60rpx; height: 34rpx; border: none; color: #333; text-align: center; font-size: 26rpx; } } } } } .index-cart{ width: 100%; height: 80rpx; display: flex; align-items: center; justify-content: flex-start; position: relative; z-index: 3; .left{ width: 470rpx; height: 100%; background: #3e3a39; display: flex; align-items: center; justify-content: flex-start; .cart-num{ width: 100rpx; height: 100rpx; background: #6e6d6c; position: relative; padding:25rpx; box-sizing: border-box; border-radius: 100%; top: -30rpx; left: 22rpx; &.on{ background: $base-color; } image{ width: 50rpx; height: 50rpx; } text{ font-size: 20rpx; color: #fff; display: inline-block; padding: 0 9rpx; box-sizing: border-box; position: absolute; right: 3rpx; top: -3rpx; height: 30rpx; line-height: 30rpx; border-radius: 30rpx; background: #f00; } } .cart-money{ color: #fff; font-size: 30rpx; margin-left: 50rpx; } } .order-btn{ width: 280rpx; height: 100%; background: $base-color; font-size: 28rpx; color: #fff; display: flex; align-items: center; justify-content: center; } } }
4.ps
小程序使用mpx为框架;
商品列表数据根据接口获取,测试数据可以根据mock数据测试
实际数据类型是
goodlists: [ { id: 'xx', name: 'xx', // 商品类型 list: [ // 当前商品类型对应的所有商品 { id: 'xx', title: 'xx', pic: 'xx', price: 'xx', detail: 'xx', num: '' // num是为了我方便对商品加减操作,让后端加的 } ] } ]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。