uniapp实现购物车功能

24 篇文章 0 订阅

uniapp实现购物车功能

周六我看见一个有个公司招聘需要试岗3天,并使用uniapp完成购物车,直播间,地图,首页四个功能方能通过,于是乎,我趁手上没事就打算自己写一遍,虽然我的项目没用到,但是多掌握点总没错。今天就来第一个——购物车
在这里插入图片描述

因为没写接口,上面的数据我都是使用的模拟数据搭建而成,主要实现的是它件数的增加减少与支付总价格的逻辑关系,还有左边的全选和全不选。
首先第一步,我们把页面先搭建出来

<template>
	<view>
	//购物车没商品出现的页面
		<view class="empty" v-if="show==false">
			<image src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F01%2F82%2F40%2F596fa6dc00bb4_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633499781&t=d37222e32213957ddbdd01d62e071309" mode="widthFix" style="width: 400rpx;"></image>
		<view class="empty-text">空空如也的购物</view>
		<view class="empty-button" @click="goshopping">去选购</view>
		</view>
		//购物车加购商品的东西
		<view v-if="show==true">
		//通过循环商品呈现出每个商品
			<view class="goods-detail" v-for="(item,index) in goods" :key="index">
				<view class="detail-left">
					<view class="goods-left">
					//商品的选择框
						<checkbox-group @change="selected(item)">
							<label>
								<checkbox  class="selected" color="#555555" :checked="checked"/>
							</label>
						</checkbox-group>
						  <image :src="item.goodsImage" mode="widthFix" style="width: 150rpx;"></image>
					</view>
					<view class="size">
					    <text style="font-size: 25rpx;">尺码:{{item.size}}</text>
					    <text class="goods-price">¥{{item.price}}/件</text>
					</view>
				</view>
				<view class="detail-right">
					<text class="subtract" @click="reduce(item)">-</text>
					<text class="num">{{item.num}}</text>
					<text @click="add(item)" class="add">+</text>
				</view>
			</view>
		</view>
		//全选总计
		<view class="end">
			<view class="end-left">
				<checkbox-group @change="selectgoods()">
					<label>
						<checkbox  :checked="allchecked" />全选
					</label>
				</checkbox-group>
				<view>
					总计:<text style="color: #f00;font-weight: bold;">¥ {{totalPrice}}</text>
				</view>
				</view>
				<view class="end-right">
				    结算({{totalNum}})
				</view>
			
			
		</view>
	</view>
</template>

这是我们页面的结构
其中最开始有一个v-if,大家都知道这是用于条件判断的

<view class="empty" v-if="show==false">
			<image src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F01%2F82%2F40%2F596fa6dc00bb4_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633499781&t=d37222e32213957ddbdd01d62e071309" mode="widthFix" style="width: 400rpx;"></image>
		<view class="empty-text">空空如也的购物</view>
		<view class="empty-button" @click="goshopping">去选购</view>
		</view>

这一块就是当我们的购物车是空的时候,页面应该呈现的样子。我也给大家截图出来了
在这里插入图片描述
最开始的那个标题栏是因为我觉得没商品的时候黄色和它更搭,有商品的时候红色更美。毕竟我们做前端的,样式还是很重要的。哈哈哈。
结构搭好了,接下来是样式的完成。

<style lang="scss">
	.goods{
		line-height: 80rpx;
		background-color: #FFFFFF;
		&-detail{
		    display: flex;
		    padding: 30rpx 15rpx 30rpx 30rpx;
		    background-color: #fff;
		    justify-content: space-between;
		    border-bottom: 5rpx solid #F1F1F1;
		    align-items: center;
		    .detail-left{
		        display: flex;
		        .goods-left{
		            display: flex;
		            align-items: center;
		        }
		    }
		    .size{
		        display: flex;
		        justify-content: space-around;
		        flex-direction: column;
		        margin-left: 30rpx;
		        .goods-price{
		            font-size: 25rpx;
		            color: #F44545;
		            
		        }
		    }
		    .detail-right{
		        text{
		            width: 50rpx;
		            line-height: 50rpx;
		            text-align: center;
		            display: inline-block;
		            background-color: #F7F7F7;
		            margin-right: 10rpx;
		        }
		        .add {
		            color: #FA4305;
		            border-radius: 10rpx 30rpx 30rpx 10rpx;
		            margin-right: 20rpx;
		        }
		        .subtract{
		            border-radius: 30rpx 10rpx 10rpx 30rpx;
		        }
		    }
		}
	}
	.empty{
		
		    position: relative;
		    top: 220rpx;
		    text-align: center;
		    display: flex;
		    align-items: center;
		    flex-direction: column;
		    &-text{
		        color: #808080;
		        margin-bottom: 50rpx;
		    }
		    &-button{
		        width: 300rpx;
		        height: 90rpx;
		        color:orange;
		        border: 1rpx solid orange;
		        text-align: center;
		        line-height: 90rpx;
		        border-radius: 48rpx;
		    }		
	}
	.end{
	    width: 100%;
	    height: 90rpx;
	    background-color:#fff;
	    position: fixed;
	    bottom: 100rpx;
	    left: 0;
	    display: flex;
	    align-items: center;
	    &-left{
	        width: 70%;
	        display: flex;
	        justify-content: space-between;
	        padding: 0 30rpx;
	        .end-flex{
	            display: flex;
	            align-items: center;
	        }
	    }
	    &-right{
	        width: 30%;
	        line-height: 90rpx;
	        background-color: #F44545;
	        text-align: center;
	        color: #fff;
	    }
	}
</style>

基本结构样式写完以后就变成刚刚我们看到的第一张图了,接下来就是对功能的实现了。
先把我们页面需要的假数据写出来

<script>
	export default{
		data(){
			return{
			//购物车有无商品
				show:true,
				//全选是否选中
				 allchecked:true,
				    checked:true,
				    //商品
					goods:[{
						size:"女款-M",
						num:1,
						flag:true,
						price:149,
						goodsImage:"https://img0.baidu.com/it/u=4158246207,3235707994&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-xs",
						num:1,
						flag:true,
						price:219,
						goodsImage:"https://img0.baidu.com/it/u=811765333,1656843554&fm=11&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-L",
						num:1,
						flag:true,
						price:240,
						goodsImage:"https://img1.baidu.com/it/u=233755383,2522308225&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-XXL",
						num:1,
						flag:true,
						price:410,
						goodsImage:"https://img0.baidu.com/it/u=3894000947,2570065196&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-XXL",
						num:1,
						flag:true,
						price:500,
						goodsImage:"https://img2.baidu.com/it/u=1001625387,3275765924&fm=26&fmt=auto&gp=0.jpg",
					},
					],
			}
		},
		method:{},
		computed:{}
		}
	</script>	

接下来就是实现各个功能了,在方法中定义我们需要的
首先页面上有个跳转,在购物车没有东西的时候,我们需要跳转页面去挑选东西

goshopping(){
				uni.navigateTo({
					url:'../contact/contact'
				})
			},

地址根据自己需要的页面地址书写。
接下来就要处理我们每个商品旁边的复选框选中状态与我们全选的关系。
如果所有商品都是选中状态,那我们的全选框也应该被选中。

  • 先来判断单个商品的selected(item)
    1.如果商品都没被选中,则全选为空。
    2.通过循环所有商品,如果全部的flag==true,则表示都被选中,则全选选中,有一个没被选中,全选都应该处于没选中状态。
    代码如下:

    selected(item){
    item.flag=!item.flag
    if(!item.flag){
    this.allchecked=false

    			}else{
    				const a=this.goods.forEach((item)=>{
    					return item.flag===true
    				})
    				if(a){
    					this.allchecked=true
    				}else{
    					this.allchecked=false
    				}
    			}
    		},
    

通过判断单选来实现全选的功能后,接下来我们也要通过全选按钮来控制所有商品的选中状态

  • 再来注册全选按钮事件selectgoods()
    1.点击全选按钮,所有商品全部选中
    2.取消全选选中状态,商品全部处于没选中。

    selectgoods(){
    this.allchecked=!this.allchecked
    if(this.allchecked){
    this.goods.map(item=>{
    this.checked=true
    item.flag=true
    })
    }else{
    this.checked=false
    this.goods.map(item=>{
    item.flag=false
    })
    }
    },

处理完左边的商品选中状态以后,接下来我们要实现对商品的数量的处理,
首先要实现商品数量的增减,一般来说,商品数量是不可能的为0的,为0则表示商品已经不在,所以该商品数量至少为1。
在这里插入图片描述

  • 商品数量的增加add,
    点击+号数量增加一

    add(item){
    let num =item.num
    item.num=num+1
    }

  • 商品数量的减少
    1.点击则数量减少1
    2.数量最少为1,为1后则不能递减

    reduce(item){
    let num=item.num
    if(num>1){
    num-=1
    }else if(num=1){
    uni.showToast({
    title:“该宝贝不能减少了哟~”
    })
    }
    item.num=num
    },

在这里插入图片描述
在处理完商品的数量后,本节的重头戏来了,我们还剩下我们的结算金额还没有计算出来,还有购买的总计商品数量也没有显示。
在这里插入图片描述
结算的总金额=(每个商品的单价*每个商品的数量)的总和

  • 先来计算购买商品的数量totalNum()
    1.商品数量初始量为0
    2.从上到下将商品进行遍历
    3.通过判断flag,商品有数量的就把数量num加入总计数,没有的就返回总数量

    totalNum(){
    let totalNum = 0;
    this.goods.map(item => {
    item.flag ? totalNum += item.num : totalNum += 0
    })
    return totalNum
    },

在这儿不得不说我的最爱,三元表达式,真的是太喜欢了。
总数量解决好后,来计算我们的总价格,也就是我们的支付价格。

  • 总价格=商品1的单价_商品1的数量+商品2的单价_商品2的价格+…+商品n的单价*商品n的价格

    totalPrice() {
    		    let totalPrice = 0;
    		    this.goods.map(item => {
    		        item.flag ? totalPrice += item.num * item.price : totalPrice += 0
    		    })
    		    return totalPrice
    		}
    

就这样我们的简单的购物车功能就完成了,是不是很简单呢,里面的逻辑性都不是很强。
最后我再附上全部的完整的代码,个人经验上面代码分散的真的不是很好看。

<template>
	<view>
		<view class="empty" v-if="show==false">
			<image src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F01%2F82%2F40%2F596fa6dc00bb4_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633499781&t=d37222e32213957ddbdd01d62e071309" mode="widthFix" style="width: 400rpx;"></image>
		<view class="empty-text">空空如也的购物</view>
		<view class="empty-button" @click="goshopping">去选购</view>
		</view>
		<view v-if="show==true">
			<view class="goods-detail" v-for="(item,index) in goods" :key="index">
				<view class="detail-left">
					<view class="goods-left">
						<checkbox-group @change="selected(item)">
							<label>
								<checkbox  class="selected" color="#555555" :checked="checked"/><text></text>
							</label>
						</checkbox-group>
						  <image :src="item.goodsImage" style="width: 150rpx;height: 140rpx;"></image>
					</view>
					<view class="size">
					    <text style="font-size: 25rpx;">尺码:{{item.size}}</text>
					    <text class="goods-price">¥{{item.price}}/件</text>
					</view>
				</view>
				<view class="detail-right">
					<text class="subtract" @click="reduce(item)">-</text>
					<text class="num">{{item.num}}</text>
					<text @click="add(item)" class="add">+</text>
				</view>
			</view>
		</view>
		<view class="end">
			<view class="end-left">
				<checkbox-group @change="selectgoods()">
					<label>
						<checkbox  :checked="allchecked" />全选
					</label>
				</checkbox-group>
				<view>
					总计:<text style="color: #f00;font-weight: bold;">¥ {{totalPrice}}</text>
				</view>
				</view>
				<view class="end-right">
				    结算({{totalNum}})
				</view>
			
			
		</view>
	</view>
</template>

<script>
	export default{
		data(){
			return{
				show:true,
				 allchecked:true,
				    checked:true,
					goods:[{
						size:"女款-M",
						num:1,
						flag:true,
						price:149,
						goodsImage:"https://img0.baidu.com/it/u=4158246207,3235707994&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-xs",
						num:1,
						flag:true,
						price:219,
						goodsImage:"https://img0.baidu.com/it/u=811765333,1656843554&fm=11&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-L",
						num:1,
						flag:true,
						price:240,
						goodsImage:"https://img1.baidu.com/it/u=233755383,2522308225&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-XXL",
						num:1,
						flag:true,
						price:410,
						goodsImage:"https://img0.baidu.com/it/u=3894000947,2570065196&fm=26&fmt=auto&gp=0.jpg",
					},
					{
						size:"女款-XXL",
						num:1,
						flag:true,
						price:500,
						goodsImage:"https://img2.baidu.com/it/u=1001625387,3275765924&fm=26&fmt=auto&gp=0.jpg",
					},
					],
			}
		},
		methods:{
			goshopping(){
				uni.navigateTo({
					url:'../contact/contact'
				})
			},
			change(e){
				console.log(e)
			},
			selected(item){
				item.flag=!item.flag
				if(!item.flag){
					this.allchecked=false
					
				}else{
					const a=this.goods.forEach((item)=>{
						return item.flag===true
					})
					if(a){
						this.allchecked=true
					}else{
						this.allchecked=false
					}
				}
			},
			selectgoods(){
				this.allchecked=!this.allchecked
				if(this.allchecked){
					this.goods.map(item=>{
						this.checked=true
						item.flag=true
					})
				}else{
					this.checked=false
					this.goods.map(item=>{
						item.flag=false
					})
				}
			},
			reduce(item){
				let num=item.num
				if(num>1){
					num-=1
				}else if(num=1){
					uni.showToast({
					                    title:"该宝贝不能减少了哟~" 
					                })
				}
					
				
				item.num=num
			},
			add(item){
				let num =item.num
				item.num=num+1
			}
		},
		computed:{
			totalNum(){
				let totalNum = 0;
				this.goods.map(item => {
				    item.flag ? totalNum += item.num : totalNum += 0
				})
				return totalNum
			},
			
			totalPrice() {
			    let totalPrice = 0;
			    this.goods.map(item => {
			        item.flag ? totalPrice += item.num * item.price : totalPrice += 0
			    })
			    return totalPrice
			}
		}
	}
	
</script>

<style lang="scss">
	.goods{
		line-height: 80rpx;
		background-color: #FFFFFF;
		&-detail{
		    display: flex;
		    padding: 30rpx 15rpx 30rpx 30rpx;
		    background-color: #fff;
		    justify-content: space-between;
		    border-bottom: 5rpx solid #F1F1F1;
		    align-items: center;
		    .detail-left{
		        display: flex;
		        .goods-left{
		            display: flex;
		            align-items: center;
		        }
		    }
		    .size{
		        display: flex;
		        justify-content: space-around;
		        flex-direction: column;
		        margin-left: 30rpx;
		        .goods-price{
		            font-size: 25rpx;
		            color: #F44545;
		            
		        }
		    }
		    .detail-right{
		        text{
		            width: 50rpx;
		            line-height: 50rpx;
		            text-align: center;
		            display: inline-block;
		            background-color: #F7F7F7;
		            margin-right: 10rpx;
		        }
		        .add {
		            color: #FA4305;
		            border-radius: 10rpx 30rpx 30rpx 10rpx;
		            margin-right: 20rpx;
		        }
		        .subtract{
		            border-radius: 30rpx 10rpx 10rpx 30rpx;
		        }
		    }
		}
	}
	.empty{
		
		    position: relative;
		    top: 220rpx;
		    text-align: center;
		    display: flex;
		    align-items: center;
		    flex-direction: column;
		    &-text{
		        color: #808080;
		        margin-bottom: 50rpx;
		    }
		    &-button{
		        width: 300rpx;
		        height: 90rpx;
		        color:orange;
		        border: 1rpx solid orange;
		        text-align: center;
		        line-height: 90rpx;
		        border-radius: 48rpx;
		    }		
	}
	.end{
	    width: 100%;
	    height: 90rpx;
	    background-color:#fff;
	    position: fixed;
	    bottom: 100rpx;
	    left: 0;
	    display: flex;
	    align-items: center;
	    &-left{
	        width: 70%;
	        display: flex;
	        justify-content: space-between;
	        padding: 0 30rpx;
	        .end-flex{
	            display: flex;
	            align-items: center;
	        }
	    }
	    &-right{
	        width: 30%;
	        line-height: 90rpx;
	        background-color: #F44545;
	        text-align: center;
	        color: #fff;
	    }
	}
</style>
  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UniApp实现购物车的全选、单选和反选功能,可以通过以下步骤进行操作: 1. 数据结构设计:首先,你需要定义一个购物车数据结构,可以使用数组或对象来表示每个商品的信息,例如商品名称、价格、数量等。同时,为每个商品添加一个选中状态的属性,用于记录是否被选中。 2. 渲染购物车列表:在页面中使用`v-for`指令遍历购物车数据,并将商品信息展示出来。同时,为每个商品的选中状态绑定一个`v-model`指令,用于实现单选功能。 3. 实现全选功能:添加一个全选的复选框,通过绑定一个变量来控制全选的状态。当全选复选框被点击时,遍历购物车数据,将每个商品的选中状态与全选状态保持一致。 4. 实现反选功能:添加一个反选按钮,当点击反选按钮时,遍历购物车数据,将每个商品的选中状态取反。 5. 计算总价和总数量:通过遍历购物车数据,累加选中商品的价格和数量,得到总价和总数量。 6. 相关代码示例: ```html <template> <div> <div> <input type="checkbox" v-model="selectAll" @change="handleSelectAll" /> 全选 <button @click="handleInverseSelect">反选</button> </div> <div v-for="(item, index) in cartList" :key="index"> <input type="checkbox" v-model="item.selected" @change="handleSelectItem(index)" /> {{ item.name }} - ¥{{ item.price }} - 数量:{{ item.quantity }} </div> <div> 总价:¥{{ totalPrice }},总数量:{{ totalQuantity }} </div> </div> </template> <script> export default { data() { return { selectAll: false, cartList: [ { name: '商品1', price: 10, quantity: 1, selected: false }, { name: '商品2', price: 20, quantity: 2, selected: false }, { name: '商品3', price: 30, quantity: 3, selected: false } ] }; }, computed: { totalPrice() { let total = 0; for (let item of this.cartList) { if (item.selected) { total += item.price * item.quantity; } } return total; }, totalQuantity() { let total = 0; for (let item of this.cartList) { if (item.selected) { total += item.quantity; } } return total; } }, methods: { handleSelectAll() { for (let item of this.cartList) { item.selected = this.selectAll; } }, handleSelectItem(index) { this.cartList[index].selected = !this.cartList[index].selected; }, handleInverseSelect() { for (let item of this.cartList) { item.selected = !item.selected; } } } }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值