JavaScript

超轻量级php框架startmvc

小程序外卖订单界面的示例代码

更新时间:2020-09-28 19:42:02 作者:startmvc
1.效果界面2.涉及功能*左侧商品类型、右侧商品可以相互控制;*商品列表加减及购物车商品

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是为了我方便对商品加减操作,让后端加的
 }
 ]
 }
]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

小程序外卖订单界面 小程序外卖订单